Moisés Gualapuro - moises.gualapuro@ikiam.edu.ec - Universidad Regional Amazónica IKIAM, Tena (Ecuador)

CONTENIDO

Resultados de Aprendizaje

Al finalizar la unidad, el estudiante será capaz de:

  1. Introducción a R
  • Instalar R y Rstudio en el equipo personal

  • Crear su usuario en Rstudio cloud (https://rstudio.cloud/)

  • Tener familiaridad con el entorno de Rstudio

  • Utilizar las operaciones matemáticas fundamentales.

  • Identificar los tipos de datos comunes en R.

  • Operar con los diferentes tipos de datos en R.

  • Utilizar data precargada en R

  1. Estructuras de Control
  • Condicional if

  • Bucle while

  • Bucle for

  1. Funciones

  2. Manipulación de datos

  • Data precargada

  • Importación de datos

  • Manipulación de datos

  • Manipulación de data grande

1. INTRODUCCIÓN A R

R es un lenguaje de programación para estadística computacional. Es un paquete de software libre disponible bajo GNU Licencia General Pública. R y sus librerías están diseñadas para estadística y visualización, entre ellas las estadísticas descriptivas, inferencias estadísticas y análisis de regresión.

1.1. Ventajas del uso de R

1.2. Desventajas del uso de R

  • R podría consumir toda la memoria RAM disponible, dificulta el trabajo con datos masivos.

  • No se puede reclamar si algo no funciona.

  • La calidad de algunos paquetes puede no ser ideal.

  • Al inicio no es user-friendly. La curva de aprendizaje es lenta al inicio, luego es exponencial.

  • Fácil equivocarse y no reconocer dónde se encuentra el error.

1.3. Instalación de R y RStudio

1.3.1 Instalar R

R se puede descargar de https://cran.r-project.org; luego se debe seguir las instrucciones e instalar con las opciones predeterminadas.

En Ubuntu se ejecuta en el terminal: sudo apt-get install r-base.

1.3.2 Instalar RStudio

Después de instalar R, se debe instalar RStudio desde: https://rstudio.com/products/rstudio/download/; se debe seguir las instrucciones e instalar con las opciones predeterminadas.

1.3.3. RStudio Cloud

Ingresar a https://rstudio.cloud y crear un usuario como en cualquier plataforma de correo o red social.

1.3.4. Ambiente de R en el terminal y en RStudio

1.3.4.1 Consola de R o R en el terminal

La primera opción es abrir la consola de R base:

La segunda opción es abrir el terminal (Ctrl + Alt + t) o la línea de comando (cmd)

1.3.4.2 R en RStudio

La tercera opción es usar R con RStudio.

“RStudio es un integrated development environment (IDE) para R. Incluye una consola, editor con resaltador-sintáctico que soporta la ejecución de código, asimismo herramientas de gráfica, registro histórico, debugging y administración del entorno de trabajo (workspace)”

Al abrir RStudio se tendrá la siguiente ventana:

En el interfaz de RStudio se tiene 4 áreas, además de la barra de opciones en la parte superior.

  • Área Superior - Izquierda: es el editor de sintaxis; se trata del lugar donde editamos la sintaxis para posteriormente ejecutarla. Al escribir allí no sucederá nada, a no ser que se apriete algún botón para ejecutar los comandos o la tecla ctrl+enter.

  • Área Superior - Derecha: es el “entorno de trabajo” del programa: en este lugar se muestra el conjunto de datos y los “objetos” (resultados, variables, gráficos, etc.) que se almacenan al ejecutar diferentes análisis.

  • Área Inferior - Derecha: paneles de archivos, de salida, de paquetes y de ayuda;

    1. la pestaña files permite ver el historial de archivos trabajados con el programa;

    2. la pestaña plots permite visualizar los gráficos que se generen;

    3. la pestaña packages permite ver los paquetes descargados y guardados en el disco duro así como gestionar su instalación o actualización;

    4. la ventana help permite acceder al CRAN - Comprehensive R Archive Network (siempre que se cuente con conexión a Internet), página oficial del software que ofrece diferentes recursos para el programa: manuales para el usuario, cursos on line, información general, descarga de paquetes, información de los paquetes instalados, etc. Esta última pestaña es bastante útil: empleando el motor de búsqueda se accede de manera rápida a manuales de uso de los diferentes paquetes (y sus funciones) instalados en el computador (esto no requiere conexión a Internet).7;

    5. la ventana viewer muestra los resultados al construir reportes mediante funcionalidades tipo rmarkdown.

  • Área Inferior - Izquierda: es la consola. Corresponde a lo que sería el software R en su versión básica. Allí el software ejecuta las operaciones realizadas desde el editor de sintaxis.

1.4. Componentes del interfaz de RStudio

Las funcionalidades señalados a continuación están disponibles en: https://github.com/rstudio/cheatsheets/blob/master/translations/spanish/rstudio-ide_Spanish_Translation_Monica_Alonso.pdf

1.4.1. Configuración base

Revisión de la versión de R

version
##                _                           
## platform       x86_64-w64-mingw32          
## arch           x86_64                      
## os             mingw32                     
## system         x86_64, mingw32             
## status                                     
## major          4                           
## minor          1.2                         
## year           2021                        
## month          11                          
## day            01                          
## svn rev        81115                       
## language       R                           
## version.string R version 4.1.2 (2021-11-01)
## nickname       Bird Hippie

1.5. Instalar paquetes

La versión predertimanada de R tiene varias funciones previamente cargadas. Por otro lado, se tiene funciones más especializadas que se desarrollan en forma de paquetes que se requieren ser instaladas desde el repositorio de R denominada CRAN (https://cloud.r-project.org/). Para revisar el paquete disponible debe dirigirse a la sección “Software/Packages”. Aquí encontrará un aproximado de 16395 paquetes.

Para instalar alguno de ellos se debe usar el código:

# Revisar paquetes instalados
#installed.packages("forensic")

# Instalar un único paquete, install.packages("nombrepaquete")
#install.packages("forensic")

# Grupo de paquetes, install.packages(c("nombrepaquete1", "nombrepaquete2",...)) 
#install.packages(c("tinytest", "abdiv"))

# Instalar solamente si se requiere
#if(require("forensic")) install.packages("forensic")

# Actualizar un paquete
#update.packages("car")

# Remover o desinstalar paquete(s) 
#remove.packages("abdiv")

1.6. Ayuda

Se puede utilizar la orden help("nombrefuncion") o ?nombrefuncion o ??nombrefuncion_

# Revisar información de ayuda y ejemplos. Se puede escribir:
# Ayuda de una función
?mean
help(mean)
??sqrt
help(sqrt)

# Ayuda de un paquete: Se puede escribir 
??ggplot

La información de ayuda se desplegará en la ventana inferior-derecha, donde se muestra la: descripción, usos, argumentos, valores, referencias y ejemplos. Si la función es implementado en varios módulos, se presentará el listado de módulos para seleccionar.

1.6.1. Ayuda en fuentes externas

Si la información disponible en Help es insuficiente o no logra corregir algo por cuenta propia, se recomienda hacer la busqueda del tema en plataformas como:

1.8. Operaciones fundamentales

1.8.1 Operaciones numéricas

OPERADOR DESCRIPCIÓN
+ Suma, adición
- Resta, sustracción
* Multiplicación, producto
/ División
^ o ** Exponenciación
`x %% y` Módulo o remanente
`x %/% y` Dicisión entera
`==` Igual a
`!=` No igual a
> Mayor que
< Menor que
>= Mayor o igual que
<= Menor o igual que
& Lógico “Y”
| Lógico “o”
! Lógico “no”
# Suma 
3+5
## [1] 8
# Resta 
5-3
## [1] 2
# Multiplicación
3*4
## [1] 12
# División
12/3
## [1] 4
# Exponente
4^3
## [1] 64
exp(2) # valor exp = e = 2.7182818, exp(2)= e^2 =7.389056
## [1] 7.389056
# Modulo o restante
3%%2
## [1] 1
4%%2
## [1] 0
# División entera

18%/%5
## [1] 3
# Raíz
sqrt(9)
## [1] 3
# Logaritmo (log en base e, log10 en base 10, log2 en base 2)
log(exp(2))
## [1] 2
log(7)
## [1] 1.94591
log10(1000)
## [1] 3
log10(20)
## [1] 1.30103
log2(64)
## [1] 6
log2(30)
## [1] 4.906891
logb(125, base=5)
## [1] 3
logb(125, base=3)
## [1] 4.394921
# Trigonométricas (escribir los ángulos en radianes)
sin(pi) # valor pi =3.1415927
## [1] 0.0000000000000001224606
sin(pi/3)
## [1] 0.8660254
cos(pi/4)
## [1] 0.7071068
tan(3*pi/5)
## [1] -3.077684

1.8.2 Operaciones de relación

Las operaciones de relación comparan el orden de los valores numéricos o alfabéticos y siempre retornan valores booleanosTRUE o FALSE. Por ejemplo, si hacemos la operación 2<5, la respuesta que retorna es TRUE porque el valor 2 es menor que el valor 5. Asimismo, si hacemos la operación "a">"c", la respuesta que retorna es FALSE porque la letra a en el alfabeto se encuentra a la antes que la letra c. Así también se puede comparar palabras "papaya" <"papagayo"

# Menor 
3 < 5
## [1] TRUE
4 < 6
## [1] TRUE
"a" < "c"
## [1] TRUE
"d" < "b"
## [1] FALSE
# Mayor
2>3
## [1] FALSE
3>2
## [1] TRUE
"a" > "c"
## [1] FALSE
"m" > "b"
## [1] TRUE
# Menor o igual que
3<=4
## [1] TRUE
4<=8/2
## [1] TRUE
"a" <= "b"
## [1] TRUE
"m" <= "m"
## [1] TRUE
# Mayor o igual que
5>=4
## [1] TRUE
2>=8/2
## [1] FALSE
"m" >= "b"
## [1] TRUE
"p" <= "t"
## [1] TRUE
# Igual a 
2 == (8/4)
## [1] TRUE
# No igual a 
3 !=4
## [1] TRUE
# Comparar palabras
"papaya" <"papagayo"
## [1] FALSE

1.8.3 Operaciones lógicas

En estas operaciones se usan operadores lógicos para concatenar operaciones de relación simples y siempre el resultado es TRUE (verdadero, 1) o FALSE (falso, 0). Entre los operadores lógicos fundamentales se tiene:

  • AND (&) operador “y”, solo cuando las dos operaciones simples son verdaderas resultado de la operación es verdadera. Por ejemplo: 2+3==5 es verdadero y 3^2 >= 9 tambien es verdadero, entonces el resultado de (2+3==5) & (3^2 >= 9) será verdadero.

  • OR (|) operador “o”, solo si las dos operaciones simples son falsas resulta en falso; si alguno de los es verdadero, entonces la operación es verdad. Por ejemplo: 2+3>5 es falso y 3^2 != 9 tambien es falso, entonces el resultado de (2+3>5) & (3^2 != 9) será falso.

  • NOT(!) operador “no” o de negación. Cambia el valor lógico de TRUE a !TRUE o FALSE.

# Operador AND
(3<4) & (4/2==2)
## [1] TRUE
(3>4) & (4/2==2)
## [1] FALSE
(3<4) & (4/2!=2)
## [1] FALSE
(3>4) & (4/2!=2)
## [1] FALSE
# Operador OR
(3<4) | (4/2==2)
## [1] TRUE
(3>4) | (4/2==2)
## [1] TRUE
(3<4) | (4/2!=2)
## [1] TRUE
(3>4) | (4/2!=2)
## [1] FALSE
# Operador NOT
!(3<4)
## [1] FALSE
!(3==4)
## [1] TRUE
# Combinación AND, OR, NOT
!(3!=4)&((4>=5)|(2>0))
## [1] FALSE

1.8.4 Operación de asignación

En la operacione de asignación se asignan valores a las variables. Los simbolos de asignación son <-, =, <<-, -> y ->>. La primera simbología es la más utilizada en R. Para asignar, se requiere generar los nombres de las variables.

1.8.4.1 Identificadores

Se recomienda generar el nombre de las variables con palabras que den sentido a los valores a los que hace referencia. También se recomienda utilizar nombres de variables que contengan letras, dígitos ·, _. Asimismo con las siguientes consideraciones:

  • Iniciar los nombres con una letra ancho, ancho.ala, ancho_ala, anchoAla, anchoAla, ancho.aleta1, ancho.aleta15.

  • Se puede iniciar con _, pero el caracter inmediato no debe ser dígito. _ancho.aleta1

  • Evitar el uso de uso de palabras reservadas como TRUE, FALSE, mean, sqrt, if, for, while, function. Éstas palabras tienen significados y funciones especiales y predefinidas en R, por ende no se pueden usar como identificadores. Para consultar otras palabras reservadas digite ?Reserved.

1.8.4.2 Asignar valor a identificadores

Al asignar valores a los identificadores se crea un objeto y éste se almacena y se visualiza en el espacio de “Environment” (región superior derecha). Constantes:

# Asignación con "<-"
nombre <-"Carlitos"
edad <- 25
cabello <- "negro"


# Asignación con "="
especie = "Zea mays"
variedad = "INIAP29"
mazorcas <- 3
altura_flor <- 150 # medidos en centímetros (cm)

# Asignación con "<<-"
cumbre <<-"Cotopaxi"
altura <<- 5897 # medido en metros
latitud <<- 0.683 # Sur
longitud <<- 78.436 # Oeste

# Asignación con ">-"
vitamina = "Ácido ascórbico" # Vitamina C
organo <- "hígado" 
concentracion <<- 7.98 # medidos en mg/L para muestra de la población alemana

1.9. Tipos de datos

1.9.1. Tipos de valores

Previamente se asignaron algunos valores a los identificadores. Algunos de los tipos de valores son:

  • Lógicas (boolean): True, 1 o False, 0

  • Numérico entero (integer): 17, -10, 213784895

  • Numérico decimales (double): 1.0, 11.232, pi, 2.718

  • Numérico complejo (complex): 5-2i

  • Texto (character): "Los días de la semana", "Bienvenidos"

  • Categórico (factor): es un tipo de vector que tiene características de grupo y se lo convierte al utilizar as.factor(vector). Algunos ejemplos son: "Excelente", "Muy bueno", "Bueno", "Urbano", "Rural", "Costa", "Sierra", "Amazonía", "Galápagos"

  • Ausente (missing): NA

  • Vacío (empty): NULL

Para revisar el tipo de dato se debe usar el comando typeof(dato)

hoy.lunes <- TRUE
casas.manzana2 = as.integer(25)
caudal_rio1 <<- 125.13 # lts/seg
complejo <- 2+3i
carrera <- "Astrobiología"
categorico <- as.factor(c("Bueno", "Excelente", "Regular", "Muy Bueno"))
avances_tesis <- "NA"
marcianos <- ""
fechas <- 

variables <- list(hoy.lunes, casas.manzana2, caudal_rio1, complejo, 
                  carrera, categorico, avances_tesis, marcianos)

for (item in variables){
  print(paste(item, ": ", typeof(item)))
}
## [1] "TRUE :  logical"
## [1] "25 :  integer"
## [1] "125.13 :  double"
## [1] "2+3i :  complex"
## [1] "Astrobiología :  character"
## [1] "Bueno :  integer"     "Excelente :  integer" "Regular :  integer"  
## [4] "Muy Bueno :  integer"
## [1] "NA :  character"
## [1] " :  character"

1.9.2 Tipos de datos

Los valores son asignados a diferentes tipos de datos o variables, entre ellos se tiene a: vectores (vector), matrices (matrix), arreglos (array), tablas (data.frame), listas (lists).

1.9.3. Vectores

El vector es una estructura fundamental en R y puede contener un solo tipo de dato, sea este integer, double, character, complex o raw. Un vector se crea con c(elementos del vector), donde c indica concatenar o combinar. Los vectores tienen una sola fila o una sola columna de valores.

digitos <- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
constantes <- c(0.2, 3.14, 2.718)
carreras_ikiam <- c("BTC", "ECO", "GEO", "H2O", "ARQ", "AGR", "BEC", "CEX")
sitios <- t(c("sitio1", "sitio2", "sitio3")) # transpose

Explorar contenidos de vectores

Se puede hacer la exploración de los contenidos de los vectores con las siguientes órdenes:

# verificar el tipo de dato
class(digitos)
## [1] "numeric"
# número de elementos del vector 
length(digitos)
## [1] 10
# escoger un solo elemento del vector
digitos[6]
## [1] 5
# escoger todos excepto el primer elemento del vector
digitos[-1]
## [1] 1 2 3 4 5 6 7 8 9
# escoger algunos elementos del vector
digitos[3:6]
## [1] 2 3 4 5
# Operar con escalares 
digitos*3 + 2
##  [1]  2  5  8 11 14 17 20 23 26 29
sqrt(digitos-1)
##  [1]      NaN 0.000000 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490
##  [9] 2.645751 2.828427
digitos/constantes
##  [1]  0.0000000  0.3184713  0.7358352 15.0000000  1.2738854  1.8395879
##  [7] 30.0000000  2.2292994  2.9433407 45.0000000
digitos*constantes
##  [1]  0.000  3.140  5.436  0.600 12.560 13.590  1.200 21.980 21.744  1.800

Una alternativa de crear vectores es generando sequencias seq() o replicate()

secuencia0 <- 1:6

secuencia1 <- seq(from=0, to= 20, by = 0.5)
secuencia1 <- seq(0, 20, by = 0.5)
secuencia1 <- seq(0, 20, length = 40)

secuencia2 <- replicate(10, 0)
secuencia3 <- replicate(10, 3)

1.9.4. Matrices

Una matriz es una estructura bidimensional, que contiene m número de filas (horizontal) y n número de columnas (vertical).

# Transformar un vector a matriz
vector1 <- 1:30
dim(vector1) <- c(6, 5)
class(vector1)
## [1] "matrix" "array"
# Crear una matriz con matrix()
matriz2 <- matrix(2:41, 8,5) 
matriz2
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    2   10   18   26   34
## [2,]    3   11   19   27   35
## [3,]    4   12   20   28   36
## [4,]    5   13   21   29   37
## [5,]    6   14   22   30   38
## [6,]    7   15   23   31   39
## [7,]    8   16   24   32   40
## [8,]    9   17   25   33   41
# Crear una matriz uniendo vectores como columna
ciudad <- c("Quito", "Guayaquil", "Cuenca", "Ambato")
poblacion <- c(2.87, 2.98, 0.55, 0.32) # millones de personas
altura <- c(2765, 6, 2567, 2382) # sobre el nivel del mar
datos_ciudad <- cbind(ciudad, poblacion, altura)
datos_ciudad
##      ciudad      poblacion altura
## [1,] "Quito"     "2.87"    "2765"
## [2,] "Guayaquil" "2.98"    "6"   
## [3,] "Cuenca"    "0.55"    "2567"
## [4,] "Ambato"    "0.32"    "2382"
# Crear una matriz uniendo vectores como filas
especie1 <- c("Sp1", 3, "terrestre")
especie2 <- c("Sp2", 1, "acuatico")
especie3 <- c("Sp3", 5, "terrestre")
especie4 <- c("Sp4", 2, "terrestre")
especie5 <- c("Sp5", 1, "marino")
diversidad <- rbind(especie1, especie2, especie3, especie4, especie5)
diversidad
##          [,1]  [,2] [,3]       
## especie1 "Sp1" "3"  "terrestre"
## especie2 "Sp2" "1"  "acuatico" 
## especie3 "Sp3" "5"  "terrestre"
## especie4 "Sp4" "2"  "terrestre"
## especie5 "Sp5" "1"  "marino"

Explorar contenidos de matrices

Se puede hacer la exploración de los contenidos de los matrices con las siguientes órdenes:

# verificar el tipo de dato
class(datos_ciudad)
## [1] "matrix" "array"
# número de elementos de la matriz 
dim(datos_ciudad)
## [1] 4 3
# escoger un solo elemento de la matriz
datos_ciudad[2,1] # elemento de la fila 2 y columna 1
##      ciudad 
## "Guayaquil"
# escoger una fila completa
datos_ciudad[1,]
##    ciudad poblacion    altura 
##   "Quito"    "2.87"    "2765"
# escoger una columna completa
datos_ciudad[,3]
## [1] "2765" "6"    "2567" "2382"
# escoger determinadas filas y columnas
datos_ciudad[2:4,1:2]
##      ciudad      poblacion
## [1,] "Guayaquil" "2.98"   
## [2,] "Cuenca"    "0.55"   
## [3,] "Ambato"    "0.32"
# renombrar columnas
diversidad
##          [,1]  [,2] [,3]       
## especie1 "Sp1" "3"  "terrestre"
## especie2 "Sp2" "1"  "acuatico" 
## especie3 "Sp3" "5"  "terrestre"
## especie4 "Sp4" "2"  "terrestre"
## especie5 "Sp5" "1"  "marino"
colnames(diversidad)
## NULL
colnames(diversidad) <- c("Especie", "Crias","Habitat" )
diversidad
##          Especie Crias Habitat    
## especie1 "Sp1"   "3"   "terrestre"
## especie2 "Sp2"   "1"   "acuatico" 
## especie3 "Sp3"   "5"   "terrestre"
## especie4 "Sp4"   "2"   "terrestre"
## especie5 "Sp5"   "1"   "marino"
rownames(diversidad)
## [1] "especie1" "especie2" "especie3" "especie4" "especie5"

1.9.5. Arreglos

LOs arreglos son estructuras rectangulares multidimensionales para guardar datos. Las matrices son arreglos de dos dimensiones. Se generan con array()

arreglo1 <- array(1:24, dim = c(3 , 2, 4))
arreglo1
## , , 1
## 
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6
## 
## , , 2
## 
##      [,1] [,2]
## [1,]    7   10
## [2,]    8   11
## [3,]    9   12
## 
## , , 3
## 
##      [,1] [,2]
## [1,]   13   16
## [2,]   14   17
## [3,]   15   18
## 
## , , 4
## 
##      [,1] [,2]
## [1,]   19   22
## [2,]   20   23
## [3,]   21   24
dimnames(arreglo1)
## NULL
# cambiar nombres del arreglo 1
dimnames(arreglo1) <- list(c("fila1", "fila2", "fila3"), 
                           c("col1", "col2"), 
                           c("fondo1", "fondo2", "fondo3", "fondo4"))
dimnames(arreglo1)
## [[1]]
## [1] "fila1" "fila2" "fila3"
## 
## [[2]]
## [1] "col1" "col2"
## 
## [[3]]
## [1] "fondo1" "fondo2" "fondo3" "fondo4"

Explorar la información de un arreglo

arreglo1[, , 1]
##       col1 col2
## fila1    1    4
## fila2    2    5
## fila3    3    6
arreglo1[, 1, ]
##       fondo1 fondo2 fondo3 fondo4
## fila1      1      7     13     19
## fila2      2      8     14     20
## fila3      3      9     15     21

1.9.6. Data frames

Un data frame es una estructura de datos bidimensional similar a una matriz, sin embargo es una tabla simple formado por una lista de vectores de la misma longitud. Un Data frame se diferencia de una matriz en que la primera puede contener tipos de datos mixtos (numérico, lógico, caracter), mientras que el segundo tiene generalmente datos numéricos. Una dataframe se crea con data.frame(elementos)

calificaciones = data.frame(estudiante = paste0("Est", 1:20), calificacion = sample(0:10, 20, replace = TRUE))
calificaciones
##    estudiante calificacion
## 1        Est1            4
## 2        Est2            4
## 3        Est3            6
## 4        Est4            5
## 5        Est5            0
## 6        Est6            7
## 7        Est7            3
## 8        Est8            7
## 9        Est9            5
## 10      Est10            6
## 11      Est11            0
## 12      Est12            4
## 13      Est13           10
## 14      Est14            3
## 15      Est15            5
## 16      Est16            9
## 17      Est17            3
## 18      Est18            9
## 19      Est19           10
## 20      Est20            7

Explorar los elementos de data frame

Se puede utilizar df$columna para identificar una columna o tambien df["columna"]

# Seleccionar datos de una columna
calificaciones$calificacion
##  [1]  4  4  6  5  0  7  3  7  5  6  0  4 10  3  5  9  3  9 10  7
# Seleccionar datos de una columna 
calificaciones["estudiante"]
##    estudiante
## 1        Est1
## 2        Est2
## 3        Est3
## 4        Est4
## 5        Est5
## 6        Est6
## 7        Est7
## 8        Est8
## 9        Est9
## 10      Est10
## 11      Est11
## 12      Est12
## 13      Est13
## 14      Est14
## 15      Est15
## 16      Est16
## 17      Est17
## 18      Est18
## 19      Est19
## 20      Est20
# Crear una nueva columna
calificaciones$Criterio = ""
calificaciones["Nacionalidad"] = sample(c("Ecuatoriana", "Extranjera"), 
                                        20, replace=TRUE)
etnia = c("Indígena", "Afro", "Mestizo", "Blanco", "Otro")
etnias <- sample(etnia, 20, replace=TRUE)
calificaciones$Etnia = etnias

# Identificar los nombres de columnas
colnames(calificaciones)
## [1] "estudiante"   "calificacion" "Criterio"     "Nacionalidad" "Etnia"
# Selección o subconjunto df[filas, columnas]
calificaciones[5:10, 1:4]
##    estudiante calificacion Criterio Nacionalidad
## 5        Est5            0            Extranjera
## 6        Est6            7            Extranjera
## 7        Est7            3            Extranjera
## 8        Est8            7            Extranjera
## 9        Est9            5            Extranjera
## 10      Est10            6            Extranjera
# Selección o subconjunto con un criterio
cal_ecuatoriana <- subset(calificaciones, Nacionalidad == "Ecuatoriana")
cal_ecuatoriana
##    estudiante calificacion Criterio Nacionalidad    Etnia
## 2        Est2            4           Ecuatoriana     Otro
## 13      Est13           10           Ecuatoriana Indígena
## 18      Est18            9           Ecuatoriana     Otro
## 19      Est19           10           Ecuatoriana     Otro
# Selección o subconjunto multicriterio
ecu_aprobados <- subset(calificaciones, 
                        Nacionalidad == "Ecuatoriana" & calificacion >= 6)
ecu_aprobados
##    estudiante calificacion Criterio Nacionalidad    Etnia
## 13      Est13           10           Ecuatoriana Indígena
## 18      Est18            9           Ecuatoriana     Otro
## 19      Est19           10           Ecuatoriana     Otro
# Visualizar las primeras filas
head(calificaciones, 3)
##   estudiante calificacion Criterio Nacionalidad    Etnia
## 1       Est1            4            Extranjera     Otro
## 2       Est2            4           Ecuatoriana     Otro
## 3       Est3            6            Extranjera Indígena
# Visualizar las últimas filas
tail(calificaciones, 3)
##    estudiante calificacion Criterio Nacionalidad  Etnia
## 18      Est18            9           Ecuatoriana   Otro
## 19      Est19           10           Ecuatoriana   Otro
## 20      Est20            7            Extranjera Blanco

1.9.7 Listas

Una lista es una colección de elementos que pueden ser de diferente tipo. Los componentes de una lista contienen una clave y el respectivo valor. Una lista se crea con list().

listado <- list(
  "digitos"= digitos, 
  "diversidad" = diversidad, 
  "arreglo1" = arreglo1,
  "elementos" = 3, 
  "palabras" = c("estrellas", "planetas", "sateĺites"), 
  "calificaciones" = calificaciones)
listado
## $digitos
##  [1] 0 1 2 3 4 5 6 7 8 9
## 
## $diversidad
##          Especie Crias Habitat    
## especie1 "Sp1"   "3"   "terrestre"
## especie2 "Sp2"   "1"   "acuatico" 
## especie3 "Sp3"   "5"   "terrestre"
## especie4 "Sp4"   "2"   "terrestre"
## especie5 "Sp5"   "1"   "marino"   
## 
## $arreglo1
## , , fondo1
## 
##       col1 col2
## fila1    1    4
## fila2    2    5
## fila3    3    6
## 
## , , fondo2
## 
##       col1 col2
## fila1    7   10
## fila2    8   11
## fila3    9   12
## 
## , , fondo3
## 
##       col1 col2
## fila1   13   16
## fila2   14   17
## fila3   15   18
## 
## , , fondo4
## 
##       col1 col2
## fila1   19   22
## fila2   20   23
## fila3   21   24
## 
## 
## $elementos
## [1] 3
## 
## $palabras
## [1] "estrellas" "planetas"  "satelites"
## 
## $calificaciones
##    estudiante calificacion Criterio Nacionalidad    Etnia
## 1        Est1            4            Extranjera     Otro
## 2        Est2            4           Ecuatoriana     Otro
## 3        Est3            6            Extranjera Indígena
## 4        Est4            5            Extranjera   Blanco
## 5        Est5            0            Extranjera     Afro
## 6        Est6            7            Extranjera     Afro
## 7        Est7            3            Extranjera  Mestizo
## 8        Est8            7            Extranjera  Mestizo
## 9        Est9            5            Extranjera     Otro
## 10      Est10            6            Extranjera     Afro
## 11      Est11            0            Extranjera  Mestizo
## 12      Est12            4            Extranjera  Mestizo
## 13      Est13           10           Ecuatoriana Indígena
## 14      Est14            3            Extranjera     Afro
## 15      Est15            5            Extranjera     Afro
##  [ reached 'max' / getOption("max.print") -- omitted 5 rows ]

Explorar los elementos de las listas

Se puede utilizar lista$elemento o tambien un doble corchete lista[[indice]]

# uno de los elementos de la lista
listado$elementos  # cuarto elemento de la lista
## [1] 3
listado$diversidad # segundo elemento de la lista
##          Especie Crias Habitat    
## especie1 "Sp1"   "3"   "terrestre"
## especie2 "Sp2"   "1"   "acuatico" 
## especie3 "Sp3"   "5"   "terrestre"
## especie4 "Sp4"   "2"   "terrestre"
## especie5 "Sp5"   "1"   "marino"
listado[[2]] # segundo elemento de la lista
##          Especie Crias Habitat    
## especie1 "Sp1"   "3"   "terrestre"
## especie2 "Sp2"   "1"   "acuatico" 
## especie3 "Sp3"   "5"   "terrestre"
## especie4 "Sp4"   "2"   "terrestre"
## especie5 "Sp5"   "1"   "marino"
listado[[2]][1,] # fila 1 del segundo elemento de la lista
##     Especie       Crias     Habitat 
##       "Sp1"         "3" "terrestre"

3.2.6 Datos precargados en R

R tiene conjuntos de datos tabulados (datasets) que se incluyen por defecto en la instalación de R. Para enlistar los datasets de R se requiere la orden data(). Para cargar uno de los datasets solo se debe escribir el nombre y asignar a un identificador.

data()

# Selección del dataset "iris"
?iris
head(iris, 4)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
str(iris) # Estructura del dataset
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# Selección del dataset "ChickWeight"
?ChickWeight
colnames(ChickWeight)
## [1] "weight" "Time"   "Chick"  "Diet"
head(ChickWeight, 4)
##   weight Time Chick Diet
## 1     42    0     1    1
## 2     51    2     1    1
## 3     59    4     1    1
## 4     64    6     1    1
str(ChickWeight) # Estructura del dataset
## Classes 'nfnGroupedData', 'nfGroupedData', 'groupedData' and 'data.frame':   578 obs. of  4 variables:
##  $ weight: num  42 51 59 64 76 93 106 125 149 171 ...
##  $ Time  : num  0 2 4 6 8 10 12 14 16 18 ...
##  $ Chick : Ord.factor w/ 50 levels "18"<"16"<"15"<..: 15 15 15 15 15 15 15 15 15 15 ...
##  $ Diet  : Factor w/ 4 levels "1","2","3","4": 1 1 1 1 1 1 1 1 1 1 ...
##  - attr(*, "formula")=Class 'formula'  language weight ~ Time | Chick
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "outer")=Class 'formula'  language ~Diet
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "labels")=List of 2
##   ..$ x: chr "Time"
##   ..$ y: chr "Body weight"
##  - attr(*, "units")=List of 2
##   ..$ x: chr "(days)"
##   ..$ y: chr "(gm)"
chicken_diet2 <- ChickWeight[ChickWeight$Diet == "2",]

# Extraer mulltiple datasets 
ds <- c("USArrests", "VADeaths")
data(list = ds)

TAREA 1: TIPOS DE DATOS

Realice las siguientes actividades en un documento .Rmd

# Crear un identificador de nombre "ciudad" y asigne 
# como valor el nombre de alguna ciudad


# Crear un identificador de nombre "pais_andes" y asigne como valor 
# los nombres de los países por donde cruza la cordillera de Los Andes


# Crear un dataframe con 12 eventos (files) y 5 variables (columnas), 
# cada columna debe tener diferentes tipos de datos (entero, decimal, 
# caracter, logico)


# Cargue el dataset "DNase" e identifique su estructura. Extraiga (subset) 
# los datos que cumplan con las condiciones de: 
#   1. "conc" (concentracion) entre 0.1 y 0.2
#   2. "Run" diferente a 2, "conc" mayor a 0.2 y "density" menor o igual a 1.0

Referencias para refuerzo

2. ESTRUCTURAS DE CONTROL

Son instrucciones que permiten controlar el flujo de ejecución de los comandos. Estas estrucuturas posibilitan asignar operaciones lógicas en el código. Además las estructuras de control permiten reutilizar fragmentos de código una y otra vez.

2.1 Condicional if

La estrucutura condicional if relaciona el cumplimiento de una condición y luego emite una conclusión.

2.1.1 Condicional if Simple

La forma simple del condicional if emite una conclusión (mensaje o resultado) si la condición es verdadera; si es falso no se emite mensaje alguno.

if (condición) {
  ejecutar orden si es verdadera la condición
}
knitr::include_graphics('./img/ifSimple.png')
FIGURA 1: Estructura del condicional if simple

FIGURA 1: Estructura del condicional if simple

# Ejemplo de condicional simple
edad <- 20
if(edad >=18){
  mensaje <- paste("El estudiante es mayor de edad, dado que tiene", edad, "años.")
  print(mensaje)
}
## [1] "El estudiante es mayor de edad, dado que tiene 20 años."

Si la edad <- 12, entonces ningún resultado se visualiza del código anterior; por lo que se requiere completar el código para que visualice otra leyenda cuando no se cumple la condición dada.

2.1.2. Condicional if - else

La forma condicional if - else es la secuencia si cumple - entonces mensaje1 - sino mensaje2). Por ejemplo, si (if) una persona cumple con la condición de tener más de 18 años, entonces (then) se puede decir que es mayor de edad, sino (else) es menor de edad. El modelo para un if es el siguiente:

if (condición) {
  ejecutar orden cuando es verdadero la condición
}else{
  ejecutar orden cuando es falsa la condición
}
knitr::include_graphics('./img/ifelse.png')
FIGURA 2: Estructura del condicional if - else

FIGURA 2: Estructura del condicional if - else

edad <- 12
if(edad >=18){
  print(paste("El estudiante es mayor de edad, dado que tiene", edad, "años."))
}else{
  print(paste("El estudiante es menor de edad, dado que tiene", edad, "años."))
}
## [1] "El estudiante es menor de edad, dado que tiene 12 años."
edad <- 21
if(edad >=18){
  print(paste("El estudiante es mayor de edad, dado que tiene", edad, "años."))
}else{
  print(paste("El estudiante es menor de edad, dado que tiene", edad, "años."))
}
## [1] "El estudiante es mayor de edad, dado que tiene 21 años."

Actividad

Asignar un valor numérico a la variable altura. Si el valor de la altura es mayor o igual a 1200 (medidos en metros sobre el nivel del mar) debe desplegar la leyenda: Estás en la Sierra porque te encuentras a "valor" m.s.n.m. o en su defecto debe decir No estás en la Sierra porque te encuentras a "valor" m.s.n.m

# Crea tu variable "altura"

# Escribe el condicional

2.1.3. Condicional if - else if - else

La forma condicional if - else if - else es la secuencia

si1 cumple - entonces mensaje1 -- si2 - entonces mensaje2 -- si_n ... - sino mensaje3),

se puede utilizar varios else if en el código. Por ejemplo, si (if) un animal se alimenta exclusivamente de vegetales, entonces es un herbíboro, si (else if) se alimenta exclusivamente de carne, entonces es un carnívoro; si (else if) se alimenta de insectos entonces es un insectivoro; sino (else) se podría decir que es un omnívoro. El modelo para un if - else if - else es el siguiente:

if (condición) {
  ejecutar orden cuando es verdadero la condición 1
}elif{
  ejecutar orden cuando es verdadero la condición 2
}else{
  ejecutar orden cuando las condiciones 1 y 2 son falsas
}
knitr::include_graphics('./img/elif.png')
FIGURA 3: Estructura del condicional if - else if - else

FIGURA 3: Estructura del condicional if - else if - else

dieta <- "carne"
if(dieta =="hierba"){
  print(paste("El animal es herbivoro, porque su dieta se basa en ", dieta, "."))
}else if(dieta =="carne"){
  print(paste("El animal es carnívoro, porque su dieta se basa en ", dieta, "."))
}else if (dieta == "insectos"){
  print(paste("El animal es insectívoro, porque su dieta se basa en ", dieta, "."))
}else{
  print(paste("El animal es omnívoro, porque su dieta se basa en ", dieta, "."))
}
## [1] "El animal es carnívoro, porque su dieta se basa en  carne ."
edad <- 21
if(edad >=18){
  print(paste("El estudiante es mayor de edad, dado que tiene", edad, "años."))
}else{
  print(paste("El estudiante es menor de edad, dado que tiene", edad, "años."))
}
## [1] "El estudiante es mayor de edad, dado que tiene 21 años."

2.1.4 Multiples condiciones

Se puede concantenar dos o más condiciones en un if utilizando operadores lógico (y: &, o: | o no: ! ).

# Condiciones para aprobar la materia
estudiante <- "Vidal Carlos"
asistencia <- 40 # como porcentaje
promedio <- 6.2 # calificación sobre 10 puntos

# Condicional
if(asistencia >= 70 & promedio >= 6.0){
  print(paste(toupper(estudiante),"| Promedio: ", promedio, "| Asistencia: ", asistencia, "| APROBADO"))
}else{
  print(paste(toupper(estudiante),"| Promedio: ", promedio, "| Asistencia: ", asistencia, "| REPROBADO"))
}
## [1] "VIDAL CARLOS | Promedio:  6.2 | Asistencia:  40 | REPROBADO"
# Opciones en protocolo
organismo <- "Zea mays" # maíz, "Theobroma cacao" (cacao), "Manihot esculenta" (yuca)
concentracion <- 1 # medidos en ug/mml

# Condicional
if((organismo == "Zea mays" | organismo == "Theobroma cacao")& concentracion >= 5.0){
  print(paste(organismo,"| Concentración: ", concentracion, "| Protocolo 1"))
}else if((organismo == "Manihot esculenta")& concentracion >= 5.0){
  print(paste(organismo,"| Concentración: ", concentracion, "| Protocolo 2"))
}else{
  print(paste(organismo,"| Concentración: ", concentracion, "| Protocolo 3"))
}
## [1] "Zea mays | Concentración:  1 | Protocolo 3"

2.1.5 Condicional en una sola línea

Se puede imprimir un una sola línea la condicional simple de if, con la siguiente orden:

if(condición) SiVerdad.

# Disminuya la velocidad
velocidad <- 120
if(velocidad > 90) print("Disminuya su velocidad")
## [1] "Disminuya su velocidad"

Se puede aplicar la condicional if - else para un valor simple en una sola línea con la siguiente orden:

if(condición) SiVerdad else SiFalso.

nota <- 5
if(nota>=6) "Aprobado" else "Reprobado"
## [1] "Reprobado"

Se puede aplicar la condicional if - else para un vector, en una sola línea con la siguiente orden:

ifelse(condición, SiVerdad, SiFalso).

notas <- c(6,4,5,7,9.7,2.5)
ifelse(notas>=6, "Aprobado", "Reprobado")
## [1] "Aprobado"  "Reprobado" "Reprobado" "Aprobado"  "Aprobado"  "Reprobado"

2.1.6 Condicional if anidado

Se puede utilizar la condicional if dentro de otra condicional if, a esto se denomina if anidado.

knitr::include_graphics('./img/nestedif.webp')
FIGURA 4: Estructura del condicional if anidado

FIGURA 4: Estructura del condicional if anidado

set.seed(123) # semilla que hace replicable el resultado
aspirantes <- data.frame(Aspirante = paste("Aspirante",seq(1,20,by=2)),
                         Edad = sample(15:30,10,FALSE),
                         Talla = sample(100:200,10,FALSE),
                         TipoSangre = sample(c("A", "B", "O"),10,TRUE),
                         Instruccion = sample(c("Primaria", "Secundaria", "TercerNivel", "CuartoNivel"),10,TRUE))
aspirantes
##       Aspirante Edad Talla TipoSangre Instruccion
## 1   Aspirante 1   29   124          B    Primaria
## 2   Aspirante 3   30   189          O CuartoNivel
## 3   Aspirante 5   17   190          B TercerNivel
## 4   Aspirante 7   28   168          A CuartoNivel
## 5   Aspirante 9   24   198          B  Secundaria
## 6  Aspirante 11   16   156          O    Primaria
## 7  Aspirante 13   20   191          B TercerNivel
## 8  Aspirante 15   19   108          A    Primaria
## 9  Aspirante 17   18   192          O    Primaria
## 10 Aspirante 19   26   171          O  Secundaria
# if simple
aspirantes$Acceso = ifelse(aspirantes$Talla>150,"Aceptado","Rechazado")
aspirantes
##       Aspirante Edad Talla TipoSangre Instruccion    Acceso
## 1   Aspirante 1   29   124          B    Primaria Rechazado
## 2   Aspirante 3   30   189          O CuartoNivel  Aceptado
## 3   Aspirante 5   17   190          B TercerNivel  Aceptado
## 4   Aspirante 7   28   168          A CuartoNivel  Aceptado
## 5   Aspirante 9   24   198          B  Secundaria  Aceptado
## 6  Aspirante 11   16   156          O    Primaria  Aceptado
## 7  Aspirante 13   20   191          B TercerNivel  Aceptado
## 8  Aspirante 15   19   108          A    Primaria Rechazado
## 9  Aspirante 17   18   192          O    Primaria  Aceptado
## 10 Aspirante 19   26   171          O  Secundaria  Aceptado
aspirantes$Acceso = NULL
aspirantes
##       Aspirante Edad Talla TipoSangre Instruccion
## 1   Aspirante 1   29   124          B    Primaria
## 2   Aspirante 3   30   189          O CuartoNivel
## 3   Aspirante 5   17   190          B TercerNivel
## 4   Aspirante 7   28   168          A CuartoNivel
## 5   Aspirante 9   24   198          B  Secundaria
## 6  Aspirante 11   16   156          O    Primaria
## 7  Aspirante 13   20   191          B TercerNivel
## 8  Aspirante 15   19   108          A    Primaria
## 9  Aspirante 17   18   192          O    Primaria
## 10 Aspirante 19   26   171          O  Secundaria
# if anidado
# Supongamos que el primer criterio para aceptar es la talla: apto: 20 puntos, no apto: 0 puntos
# El segundo criterio es la instrucción: tercernivel y cuartonivel: 20 puntos, otros: 0 puntos
# El tecer criterio es la Edad: 18-30 años: 10 puntos, otras edades: 0 puntos

aspirantes$Puntaje <- ifelse(aspirantes$Talla >= 150 & aspirantes$Instruccion %in% c("TercerNivel","CuartoNivel") & aspirantes$Edad %in% 18:30, 50,
                             ifelse(aspirantes$Talla >= 150 & aspirantes$Edad %in% 18:30, 40,
                                    ifelse(aspirantes$Talla >= 150, 20, 0)))
aspirantes
##       Aspirante Edad Talla TipoSangre Instruccion Puntaje
## 1   Aspirante 1   29   124          B    Primaria       0
## 2   Aspirante 3   30   189          O CuartoNivel      50
## 3   Aspirante 5   17   190          B TercerNivel      20
## 4   Aspirante 7   28   168          A CuartoNivel      50
## 5   Aspirante 9   24   198          B  Secundaria      40
## 6  Aspirante 11   16   156          O    Primaria      20
## 7  Aspirante 13   20   191          B TercerNivel      50
## 8  Aspirante 15   19   108          A    Primaria       0
## 9  Aspirante 17   18   192          O    Primaria      40
## 10 Aspirante 19   26   171          O  Secundaria      40
aspirantes$Acceso <- ifelse(aspirantes$Puntaje >= 40, "Pruebas Psicométricas", "Siga Participando")
aspirantes
##       Aspirante Edad Talla TipoSangre Instruccion Puntaje                Acceso
## 1   Aspirante 1   29   124          B    Primaria       0     Siga Participando
## 2   Aspirante 3   30   189          O CuartoNivel      50 Pruebas Psicométricas
## 3   Aspirante 5   17   190          B TercerNivel      20     Siga Participando
## 4   Aspirante 7   28   168          A CuartoNivel      50 Pruebas Psicométricas
## 5   Aspirante 9   24   198          B  Secundaria      40 Pruebas Psicométricas
## 6  Aspirante 11   16   156          O    Primaria      20     Siga Participando
## 7  Aspirante 13   20   191          B TercerNivel      50 Pruebas Psicométricas
## 8  Aspirante 15   19   108          A    Primaria       0     Siga Participando
## 9  Aspirante 17   18   192          O    Primaria      40 Pruebas Psicométricas
## 10 Aspirante 19   26   171          O  Secundaria      40 Pruebas Psicométricas

2.2 Bucle while

El bucle while se utiliza cuando se desea correr indefinidamente una orden hasta que la condición sea encontrada. El siguiente es la estructura del bucle while():

while(condición){
  ejecutar repedtidamente la orden
  pasos de la variable
}
knitr::include_graphics('./img/while.png')
FIGURA 5: Estructura del bucle while

FIGURA 5: Estructura del bucle while

En el bucle while, los valores Zero, None, Null , vacío (empty) se considera que corresponden a una condición FALSE; mientras que cualquier otro valor se considera TRUE.

x <-4
while (x) {
  print(x)
  x <- x-1 # siempre se requiere definir el paso
} 
## [1] 4
## [1] 3
## [1] 2
## [1] 1
x <- -4
while (x) {
  print(x)
  x <- x+1 # siempre se requiere definir el paso
} 
## [1] -4
## [1] -3
## [1] -2
## [1] -1

El siguiente código no devuelve resultado alguno, porque él valor de la variable corresponde a FALSE.

x <- 0
while (x) {
  print(x)
  x <- x+1 # siempre se requiere definir el paso
} 

2.2.1 Bucle while con break

En ocasiones se requiere que al cumplir alguna condición, se pare la orden por completo, para ello se utiliza la función break.

while(condición){
  Ejecutar orden 
  Paso
  if(condición2) break
}
nota <- 10
while(nota){
  print(paste("Nota:", nota))
  nota <- nota - 1
  if(nota < 6)
    break
}
## [1] "Nota: 10"
## [1] "Nota: 9"
## [1] "Nota: 8"
## [1] "Nota: 7"
## [1] "Nota: 6"

2.2.2 Bucle while con next

En ocasiones se requiere que al cumplir alguna condición, se salte la orden, para ello se utiliza la función next.

while(condición){
  Paso
  if(condición2) next
  Ejecutar orden
}
nota <- 10
while(nota){
  nota <- nota - 1
  if(nota == 6)
    next
  print(paste("Nota:", nota))
}
## [1] "Nota: 9"
## [1] "Nota: 8"
## [1] "Nota: 7"
## [1] "Nota: 5"
## [1] "Nota: 4"
## [1] "Nota: 3"
## [1] "Nota: 2"
## [1] "Nota: 1"
## [1] "Nota: 0"

2.3 Bucle for

El bucle for o for loop es una función que permite iterar sobre cada elemento de un vector o una lista. La estructura del bucle for es la siguiente:

for(condición iterable){
  ejecutar repetidamente la orden
}
knitr::include_graphics('./img/for.png')
FIGURA 6: Estructura del bucle for

FIGURA 6: Estructura del bucle for

# bucle for en un vector 
colores <- c("verde", "azul", "rojo")

for(color in colores){
  print(color)
}
## [1] "verde"
## [1] "azul"
## [1] "rojo"
# bucle for en un dataframe
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
for (especie in unique(iris$Species)){
  data <- iris[iris$Species== especie,]
  print(paste(especie, length(data$Species)))
}
## [1] "setosa 50"
## [1] "versicolor 50"
## [1] "virginica 50"
# bucle for en una lista dataframe
lista <- list("a", 5, 3.15, 2+3i, c(TRUE, FALSE, TRUE), iris, mtcars)
for (item in lista){
  print(item)
}
## [1] "a"
## [1] 5
## [1] 3.15
## [1] 2+3i
## [1]  TRUE FALSE  TRUE
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1           5.1         3.5          1.4         0.2  setosa
## 2           4.9         3.0          1.4         0.2  setosa
## 3           4.7         3.2          1.3         0.2  setosa
## 4           4.6         3.1          1.5         0.2  setosa
## 5           5.0         3.6          1.4         0.2  setosa
## 6           5.4         3.9          1.7         0.4  setosa
## 7           4.6         3.4          1.4         0.3  setosa
## 8           5.0         3.4          1.5         0.2  setosa
## 9           4.4         2.9          1.4         0.2  setosa
## 10          4.9         3.1          1.5         0.1  setosa
## 11          5.4         3.7          1.5         0.2  setosa
## 12          4.8         3.4          1.6         0.2  setosa
## 13          4.8         3.0          1.4         0.1  setosa
## 14          4.3         3.0          1.1         0.1  setosa
## 15          5.8         4.0          1.2         0.2  setosa
##  [ reached 'max' / getOption("max.print") -- omitted 135 rows ]
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
##  [ reached 'max' / getOption("max.print") -- omitted 26 rows ]

2.3.1 Bucle for en una secuencia

Se puede definir el número de veces que se requiere iterar, generando una secuencia.

# Definir las veces que se itera
for (i in 1:8){
  petal_area = iris$Petal.Length[i]*iris$Petal.Width[i]
  print(paste("Area", i, ":", petal_area, "cm^2"))
}
## [1] "Area 1 : 0.28 cm^2"
## [1] "Area 2 : 0.28 cm^2"
## [1] "Area 3 : 0.26 cm^2"
## [1] "Area 4 : 0.3 cm^2"
## [1] "Area 5 : 0.28 cm^2"
## [1] "Area 6 : 0.68 cm^2"
## [1] "Area 7 : 0.42 cm^2"
## [1] "Area 8 : 0.3 cm^2"
# Iterar en para todos los elementos del vector
sepal_areas <- c()
for (i in 1:length(iris$Sepal.Length)){
  sepal_areas[i] = iris$Sepal.Length[i]*iris$Sepal.Width[i]
}
sepal_areas
##  [1] 17.85 14.70 15.04 14.26 18.00 21.06 15.64 17.00 12.76 15.19 19.98 16.32
## [13] 14.40 12.90 23.20 25.08 21.06 17.85 21.66 19.38 18.36 18.87 16.56 16.83
## [25] 16.32 15.00 17.00 18.20 17.68 15.04 14.88 18.36 21.32 23.10 15.19 16.00
## [37] 19.25 17.64 13.20 17.34 17.50 10.35 14.08 17.50 19.38 14.40 19.38 14.72
## [49] 19.61 16.50 22.40 20.48 21.39 12.65 18.20 15.96 20.79 11.76 19.14 14.04
## [61] 10.00 17.70 13.20 17.69 16.24 20.77 16.80 15.66 13.64 14.00 18.88 17.08
## [73] 15.75 17.08 18.56
##  [ reached getOption("max.print") -- omitted 75 entries ]
# alternativa rápida
df <- iris
df$Sepal_area <- df$Sepal.Length*df$Sepal.Width
head(df, 4)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal_area
## 1          5.1         3.5          1.4         0.2  setosa      17.85
## 2          4.9         3.0          1.4         0.2  setosa      14.70
## 3          4.7         3.2          1.3         0.2  setosa      15.04
## 4          4.6         3.1          1.5         0.2  setosa      14.26

2.3.2 Bucle for con break

La orden break detiene al bucle y sale por completo de ella.

elementos <- c("H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg")
for (elem in elementos){
  if (startsWith(elem,"N"))
    break
  print(elem)
}
## [1] "H"
## [1] "He"
## [1] "Li"
## [1] "Be"
## [1] "B"
## [1] "C"

2.3.3 Bucle for con next

La orden next salta al elemento que cumpla con el condicional y continua en el siguiente elemento del vector.

elementos <- c("H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg")
for (elem in elementos){
  if (startsWith(elem,"N"))
    next
  print(elem)
}
## [1] "H"
## [1] "He"
## [1] "Li"
## [1] "Be"
## [1] "B"
## [1] "C"
## [1] "O"
## [1] "F"
## [1] "Mg"
for (elem in elementos){
  if (!startsWith(elem,"N"))
    next
  print(elem)
}
## [1] "N"
## [1] "Ne"
## [1] "Na"

2.3.4 Bucle for anidado

Cuandos se requiere que algo se repita para otro item que también se repite, se utiliza el for anidado.

# Se tiene 10 estaciones metereológicas y en cada una se desea medir: "Temperatura", "Precipitación", "Radiación", "VelocidadViento"
estaciones <- factor(1:10)
medidas <- factor(c("Temperatura", "Precipitación", "Radiación", "VelViento"))

# Imprimir en la consola
for(est in estaciones){
  for(med in medidas){
    print(paste(est, med))
  }
}
## [1] "1 Temperatura"
## [1] "1 Precipitación"
## [1] "1 Radiación"
## [1] "1 VelViento"
## [1] "2 Temperatura"
## [1] "2 Precipitación"
## [1] "2 Radiación"
## [1] "2 VelViento"
## [1] "3 Temperatura"
## [1] "3 Precipitación"
## [1] "3 Radiación"
## [1] "3 VelViento"
## [1] "4 Temperatura"
## [1] "4 Precipitación"
## [1] "4 Radiación"
## [1] "4 VelViento"
## [1] "5 Temperatura"
## [1] "5 Precipitación"
## [1] "5 Radiación"
## [1] "5 VelViento"
## [1] "6 Temperatura"
## [1] "6 Precipitación"
## [1] "6 Radiación"
## [1] "6 VelViento"
## [1] "7 Temperatura"
## [1] "7 Precipitación"
## [1] "7 Radiación"
## [1] "7 VelViento"
## [1] "8 Temperatura"
## [1] "8 Precipitación"
## [1] "8 Radiación"
## [1] "8 VelViento"
## [1] "9 Temperatura"
## [1] "9 Precipitación"
## [1] "9 Radiación"
## [1] "9 VelViento"
## [1] "10 Temperatura"
## [1] "10 Precipitación"
## [1] "10 Radiación"
## [1] "10 VelViento"
#_____________________________________
# Guardar en un dataframe
datos_met <- data.frame() # Dataframe vacío
for(i in 1:length(estaciones)){
  for(j in 1:length(medidas)){
    datos_met <- rbind(datos_met , c(estaciones[i], medidas[j]))
  }
}
# cambiar nombres de columnas
names(datos_met) <- c("Estacion", "Medida")
# cambiar nombres de cada factor de la columna "Medida"
datos_met$Medida <- with(datos_met, ifelse(Medida==1, "Temperatura",
                           ifelse(Medida==2, "Precipitación",
                                  ifelse(Medida==3, "Radiación", "VelViento"))))
str(datos_met)
## 'data.frame':    40 obs. of  2 variables:
##  $ Estacion: int  1 1 1 1 2 2 2 2 3 3 ...
##  $ Medida  : chr  "VelViento" "VelViento" "VelViento" "VelViento" ...

3. FUNCIONES

Existen varias funciones pre-cargadas en R las cuales puede ser utilizadas a la vez para esscribir nuevas funciones.

Se tiene operaciones para las cuales no se tiene funciones definidas, por lo tanto deben ser escritas. Una función es un bloque de instrucciones que pueden ser utilizadas continuamente en un programa, es decir, permite automatizar operaciones. Generar funciones es más productivo que copiar y pegar las instrucciones cada vez que se necesita, por lo tanto tiene las siguientes ventajas:

  1. Se asigna un identificador que permite reconocer lo que realiza la función.

  2. Se requiere pocos cambios, en general solamente los argumentos.

  3. Se evita errores accidentales que pueden ocurrir al copiar y pegar.

  4. Se puede utilizar para escribir nuevas funciones.

  5. Se tiene una forma compacta para operar.

  6. Facilita el aprendizaje del lenguaje de programación.

La estructura de una función es la siguiente:

nombreFuncion <- function(argumento1, argumento2, ...){
  instruciones
  return(resultado)
}

Se requiere una función cuando se repite (copia y pega) una instrucción por más de tres veces. Como en el siguiente caso ejemplo, donde se busca calcular la reescalar un valor con la fórmula:

\[x_{i} = \dfrac{x-mean(x)}{sd(x)}\]

df <- data.frame(a = rnorm(10),
 b = rnorm(10),
 c = rnorm(10),
 d = rnorm(10))

df$a <- (df$a - mean(df$a, na.rm = TRUE)) / (sd(df$a, na.rm = TRUE))
df$b <- (df$b - mean(df$b, na.rm = TRUE)) / (sd(df$a, na.rm = TRUE)) # error
df$c <- (df$c - mean(df$c, na.rm = TRUE)) / (sd(df$c, na.rm = TRUE))
df$d <- (df$d - mean(df$d, na.rm = TRUE)) / (sd(df$d, na.rm = TRUE))

En este ejemplo, se repite una instrucción que podríamos optimizar generando una función. Antes de continuar vamos a revisar funciones con las cuales tenemos mayor familiaridad.

3.1 Funciones precargadas en R

Se tiene muchas funciones que ya están predefinidas en R, aquí algunas de ellas:

Ejemplos de funciones predefinidas en R
Tipo Función Descripción
Numérico abs(x) Valor absoluto [ abs(-32.3)=32.3]
sqrt(x) Raíz cuadrada [ sqrt(25)=5]
ceiling(x) Entero superior [ ceiling(2.3)=3]
floor(x) Entero inferior [ floor(2.3)=2]
trunc(x) Truncar, es seleccionar solamente el valor entero [ trunc(2.3)=2]
round(x, digits=n) Redondear [ round(2.33273427247, digits=4)=2.3327]
signif(x, digits=n) Cifras significativas [ signif(2.33273427247, digits=4)=2.3327]
cocs(x), sin(x), tan(x) Funciones trigonométricas [ cos(pi)=-1]
log(x), lo10(x), log2(x), log(x, base) Logaritmos [ logb(81 , 3)=4]
Texto substr(x, star=n1, stop=n2)

Extraer o reemplazar un “subtexto” en un vector de exto, x<- "Bienvenido al curso"

substr(x, 4, 12)="nvenido a"

substr(x, 4, 12)<-"correran al mar", x = "Biecorreran l curso"

grep(patrón, x ignore.case = FALSE, fixed=FALSE)

Busca un patrón en un vector de textos y devuelve los índice donde encuentra el patrón.

x<- c("El", "curso", "con", "R")

grep("o", x, fixed = TRUE) = 2 3]

sub(patrón, reemplazo, x, ignore.case =FALSE, fixed=FALSE)

Busca un patrón en un texto y reemplaza.

x<- c("El", "curso", "con", "R")

sub("r", "*", x, fixed = TRUE) = c("El", "cu*so", "con", "R")

strsplit(x, separador)

Separa los caracteres de un texto con separador.

x<- "Bienvenidos"

strsplit(x, "")="B" "i" "e" "n" "v" "e" "n" "i" "d" "o" "s"

paste(x, sep="")

Concatena elementos utilizando un separador.

paste("hola", "mundo", sep= "*")="hola*mundo"

paste("hola", 1:3, sep= "-")="hola-1" "hola-2" "hola-3"

paste("Hoy es", date(), sep= ":: ")="Hoy es:: Tue Oct 6 08:24:39 2020"

toupper(x)

Convierte un texto en mayúsculas

toupper("Quito")="QUITO"

tolower(x)

Convierte un texto en minúsculas

tolower("Este LUNES")="este lunes"

Estadística dnorm(x) Función de densidad normal
pnorm(x) Probabilidad acumulativa normal de x
qnorm(x) Quantil normal
rnorm(n, m=0, sd =1) Desviación normal aleatorio n, con promedio m y desviación estándar sd.
mean(x, trim=0, na.rm=FALSE)

Promedio de un vector x, donde na.rm=TRUE remueve valores NaN y trim=0.05elimina el 5% de valores extremos

mean(x, trim=0.05, na.rm=TRUE)

sd(x) Calcula la desviación estandar de un conjunto de valores.
median(x) Calcula la media de un conjunto de valores.
range(x) Calcula el rango de un conjunto de valores.
quantile(x, prob) Calcula el quantil de un conjunto de valores, dad una probabilidad (entre 0 y 1).
sum(x) Calcula la suma de un conjunto de valores.
min(x) Calcula el valor mínimo de un conjunto de valores.
max(x) Calcula el valor máximo de un conjunto de valores.
Otras funciones seq(desde, hasta, paso) Genera un vector con una secuencia de números dados el valor inicial, el valor final y el “paso” que se define.
rep(x, n) Genera un vector donde el valor x se repite por n veces.
cut(x, n) Divide una variable continua x en factores de n niveles.

Se tiene más funciones predeterminadas con las cuales se puede ir familiarizando a medida que se entrena en R.

3.2 Funciones construídas

3.2.1 Funciones simples

A continuación se crea la función cuadrado, donde el único argumento es la variable x y el resultado es \[y = x^{2}\]

# Forma de operar extensa
x<- 1
y = x**2
y
## [1] 1
x<- 2
y = x**2
y
## [1] 4
x<- 3
y = x**2
y
## [1] 9
# Forma de operar con una función 
cuadrado <- function(x) {
  y = x**2
  return(y)
}

# Se evalúa la función para algún valor
cuadrado(2)
## [1] 4
cuadrado(c(1,2,3,4,5,6,7,78,934))
## [1]      1      4      9     16     25     36     49   6084 872356
cuadrado(seq(1,10,0.2))
##  [1]   1.00   1.44   1.96   2.56   3.24   4.00   4.84   5.76   6.76   7.84
## [11]   9.00  10.24  11.56  12.96  14.44  16.00  17.64  19.36  21.16  23.04
## [21]  25.00  27.04  29.16  31.36  33.64  36.00  38.44  40.96  43.56  46.24
## [31]  49.00  51.84  54.76  57.76  60.84  64.00  67.24  70.56  73.96  77.44
## [41]  81.00  84.64  88.36  92.16  96.04 100.00
cuadrado(1:23)
##  [1]   1   4   9  16  25  36  49  64  81 100 121 144 169 196 225 256 289 324 361
## [20] 400 441 484 529
# Forma corta de la función cuadrado
(function(x) x**2)(2) # Evalúa para el valor 2 la función x^2
## [1] 4
# Otra forma corta
cuadrado2 <- function(x) x**2
cuadrado2(c(1,2,3,476))
## [1]      1      4      9 226576

Cuando se crean las funciones se pueden predefinir los valores de los parámetros, es decir si no se coloca un valor, entonces tomará el valor predeterminado.

# función potencia
potencia <- function(x=2, y=1){
  pot = x**y
  return(pot)
}

# Argumentos sin valores asignados 
potencia()
## [1] 2
# Definiendo el valor para un argumento
potencia(x=3)
## [1] 3
potencia(y=3)
## [1] 8
# Definiendo valores para ambos argumentos
potencia(x=5, y=3)
## [1] 125
potencia(5,3)
## [1] 125
# Función potencia aplicado a vectores
potencia(x = c(1,2,3,4,5,6), y=4)
## [1]    1   16   81  256  625 1296

3.2.2 Función simple 2

Para aplicar la función reescalar, se requiere utilizar la fórmula previamente indicada

df <- data.frame(a = rnorm(10),
 b = rnorm(10),
 c = rnorm(10),
 d = rnorm(10))

reescalar <- function(x){
  y = (x-mean(x))/sd(x)
  return(y)
}

reescalar(df$a)
##  [1] -0.88888972  0.23066859  0.34844408  0.02673298  0.73434356  1.65242608
##  [7] -0.41613079 -1.89615825  0.80229191 -0.59372844
colnamesdf <- colnames(df)
for (i in 1:ncol(df)){
  print(paste(colnamesdf[i], reescalar(df[,i])))
}
##  [1] "a -0.888889718407366" "a 0.23066858908586"   "a 0.348444077465671" 
##  [4] "a 0.0267329838289855" "a 0.734343559198163"  "a 1.65242608309094"  
##  [7] "a -0.416130787566984" "a -1.89615825206489"  "a 0.802291908534712" 
## [10] "a -0.593728443165099"
##  [1] "b -0.984241042037496" "b 1.64309760265583"   "b -0.365981895636257"
##  [4] "b -1.80101481684937"  "b 0.348627737436173"  "b -0.14230953395186" 
##  [7] "b 0.0794829212523827" "b 0.661374415436023"  "b -0.49766778191108" 
## [10] "b 1.05863239360565"  
##  [1] "c -0.946610786038974"  "c -0.0489412632651389" "c 1.19459944977299"   
##  [4] "c 0.119126623385072"   "c -1.11800346859132"   "c 1.27907037459783"   
##  [7] "c 1.02663619111243"    "c 0.303149559691809"   "c -0.200187170993866" 
## [10] "c -1.60883950967083"  
##  [1] "d 1.04710534248116"   "d -0.74833844176276"  "d 1.80402784494377"  
##  [4] "d 1.20455311963976"   "d -0.414541928672822" "d -1.13853885201906" 
##  [7] "d -0.849190851664753" "d 0.0364762646365098" "d -0.424605947230849"
## [10] "d -0.516946550350959"

3.2.3 Función con estrucuturas de control

Cuando se desea clasificar o agregar, se puede utilizar una función con estrucuturas de control.

aspirantes <- data.frame(Aspirante = paste("Aspirante",seq(1,20,by=2)),
                         Edad = sample(15:30,10,FALSE),
                         Talla = sample(100:200,10,FALSE),
                         TipoSangre = sample(c("A", "B", "O"),10,TRUE),
                         Instruccion = sample(c("Primaria", "Secundaria", "TercerNivel", "CuartoNivel"),10,TRUE) 
                         )

item_promedio <- function(x) {
    total <- 0
    n <- length(x)
    for (i in seq_along(x)) {
      total <- total + x[i] / n
    }
    total
  }

item_promedio(aspirantes$Edad)
## [1] 22

TAREA 2: ESTRUCTURAS DE CONTROL

Realice las siguientes actividades en un documento .Rmd

Condicional if

Asignar un valor numérico a la variable altura. Para escribir el código if - else if - else, considere las siguientes condiciones relacionadas a la altura medida en kilómetros sobre el nivel del mar:

  • Si la altura está entre 0 Km y 10 Km, que se imprima la leyenda “Estás en la Troposfera”,

  • Si la altura está entre 10 Km y 50 Km, que se imprima la leyenda “Estás en la Estratosfera”,

  • Si la altura está entre 50 Km y 85 Km, que se imprima la leyenda “Estás en la Mesosfera”,

  • Si la altura está entre 80 Km y 500 Km, que se imprima la leyenda “Estás en la Termosfera”,

  • Si la altura es mayor a los 500 Km, que se imprima la leyenda “Estás en la Exosfera”,

  • Si la altura es menor a 0 Km, que se imprima la leyenda “Escribe un valor positivo para la altura”,

# Crea tu variable "altura"

# Escribe el condicional para las capas de la atmósfera. 

Bucle for

Simule el diseño de la tabla donde guardará los resultados de un experimento, que consta de:

  • Organismos, tres tipos de especímenes, por ejemplo:

    • c(“aullador”, “chichico”, “araña”)

    • c(“polipéptido_a”, “polipéptido_b”, “polipéptido_c”)

    • c(“roca_a”, “roca_b”, “roca_c”)

  • Tratamientos, cuatro tipos de tratamientos a cada tipo de especimen, por ejemplo:

    • c(“dieta1”, “dieta2”, “dieta3”, “dieta4”)

    • c(“enzima1”, “enzima2”, “enzima3”, “enzima4”)

    • c(“aleacion1”, “aleacion2”, “aleacion3”, “aleacion4”)

  • Medidas, realizará 5 tipos de medidas, por ejemplo:

    • c(“altura”, “largo”, “masa”, “NroProgenie”, “nroSobrevivientes”)

    • c(“NroProteinas”, Estructura”, “TempDenaturacion”, “RutaMetabólica”, “PesoMolecular”)

    • c(“Composicion”, “Estructura”, “Resistencia”, “Dureza”, “Porosidad”)

Utilizando el bucle for, arme un dataframe que tenga las columnas “Especimen”, “Tratamiento” y “Medida”. El dataframe debe tener todas las combinaciones posibles de las tres columnas, por ende por lo menos 60 filas.

# Crea el dataframe vacío

# Crea las variables "Especimen", "Tratamiento" y "Medida" con sus respectivas opciones

# Escribe el código para generar el dataframe utilizando el bucle "for" anidado

# Si alguna columna tiene valores "factor", cambie por los "character()" que corresponda

TAREA 2: FUNCIONES

Realice las siguientes actividades en un documento .Rmd

# Asigne la data precargada de R "mtcars" a la variable "df_mtcars"

# Cree una función "contar_cyl" que cuente el número de veces que divida el número de carros que existe por tipo de "cyl"

# Genere una función que calcule las pendientes de los datos "mpg - hp" y guarde en la variable "pendiente_mpg.hp"

3. MANIPULACIÓN DE DATOS

3.O. Utilizar paquetes en R

R viene con múltiples funciones pre-definidos, asimismo tiene paquetes pre-instalados. Sin embargo se tiene procesamientos que requieren funcionalidades adicionales. Estas funciones se desarrollan y almancenan repositorio de R denominada CRAN (https://cloud.r-project.org/). Para revisar el paquete disponible debe dirigirse a la sección “Software/Packages”. Aquí encontrará un aproximado de 16395 paquetes.

3.0 Cargar paquetes

Para cargar los paquetes que han sido previamente instalados se debe usar la instrucción library("nombre.paquete"):

# Para maniular datos, se requerirá "readr" y "tidyverse"
library("readr")
library("tidyverse")

4. MANIPULACIÓN DE DATOS

Para manipular datos el “superpaquete” con mayor uso en R es tidyverse, cada uno de los paquetes que contiene tidyverse sirve en las etapas de análisis de datos, como se muestra en la siguiente figura:

knitr::include_graphics('./img/tidyverse.png')
FIGURA 1: Flujo de análisis de datos y paquetes de tidyverse utilizados en cada etapa

FIGURA 1: Flujo de análisis de datos y paquetes de tidyverse utilizados en cada etapa

4.1. Leer e importar archivos

Para cargar archivos se recomienda primero definir el espacio de trabajo o working directory, para ello se requiere conocer en donde el directoriodonde se está trabajando.

# Conocer el directorio de trabajo 
getwd()
## [1] "D:/GDrive/IKIAM/CLASES/2021II/2021II_GBI6/2021II_Clases/2021II_R/2021II_4.1_IntroduccionR_TiposDatos"

Teniendo el directorio de trabajo definido, podemos empezar a cargar data.

4.1.1. Generar data desde dataset precargada

# Guardar data precargada de R como un archivo csv
write.csv(mtcars, "data/df_mtcars.csv")
df_mtcars <- read_csv("data/df_mtcars.csv")
head(df_mtcars, 1)
## # A tibble: 1 x 12
##   ...1        mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
##   <chr>     <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Mazda RX4    21     6   160   110   3.9  2.62  16.5     0     1     4     4
# str(df_mtcars)

4.1.2. Generar data desde dataset de un enlace url

# Guardar data de un website como un archivo csv
library (RCurl)

# Desde un archivo de github microbioma restauración
df2 <- read_tsv("https://raw.githubusercontent.com/geohouse/Plant-Microbiomes-in-Grassland-Restorations/master/taxonomicAttributionOfAMF_OTUs.tsv")
head(df2, 1)
## # A tibble: 1 x 4
##   OTU_num Genus_Attribution Using_maxAccepts10_Jan2017_USEARCH~ Attribution_fro~
##     <dbl>             <dbl> <chr>                               <chr>           
## 1       1               289 Diversispora                        "98\tU"
# str(df2)

# Desde un archivo de github clima
df3 <- read_csv("https://raw.githubusercontent.com/afanick10/rogers-pass-snowfall/master/climate-daily.csv")
head(df3, 1)
## # A tibble: 1 x 36
##       x     y STATION_NAME           CLIMATE_IDENTIFI~ ID    LOCAL_DATE         
##   <dbl> <dbl> <chr>                              <dbl> <chr> <dttm>             
## 1 -118.  51.3 GLACIER NP ROGERS PASS           1173191 1173~ 1965-06-01 00:00:00
## # ... with 30 more variables: PROVINCE_CODE <chr>, LOCAL_YEAR <dbl>,
## #   LOCAL_MONTH <dbl>, LOCAL_DAY <dbl>, MEAN_TEMPERATURE <dbl>,
## #   MEAN_TEMPERATURE_FLAG <chr>, MIN_TEMPERATURE <dbl>,
## #   MIN_TEMPERATURE_FLAG <chr>, MAX_TEMPERATURE <dbl>,
## #   MAX_TEMPERATURE_FLAG <chr>, TOTAL_PRECIPITATION <dbl>,
## #   TOTAL_PRECIPITATION_FLAG <chr>, TOTAL_RAIN <dbl>, TOTAL_RAIN_FLAG <chr>,
## #   TOTAL_SNOW <dbl>, TOTAL_SNOW_FLAG <chr>, SNOW_ON_GROUND <dbl>, ...
# Desde un archivo de github covid_global
df4 <- read_csv("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv")
head(df4, 1)
## # A tibble: 1 x 765
##   `Province/State` `Country/Region`   Lat  Long `1/22/20` `1/23/20` `1/24/20`
##   <chr>            <chr>            <dbl> <dbl>     <dbl>     <dbl>     <dbl>
## 1 <NA>             Afghanistan       33.9  67.7         0         0         0
## # ... with 758 more variables: `1/25/20` <dbl>, `1/26/20` <dbl>,
## #   `1/27/20` <dbl>, `1/28/20` <dbl>, `1/29/20` <dbl>, `1/30/20` <dbl>,
## #   `1/31/20` <dbl>, `2/1/20` <dbl>, `2/2/20` <dbl>, `2/3/20` <dbl>,
## #   `2/4/20` <dbl>, `2/5/20` <dbl>, `2/6/20` <dbl>, `2/7/20` <dbl>,
## #   `2/8/20` <dbl>, `2/9/20` <dbl>, `2/10/20` <dbl>, `2/11/20` <dbl>,
## #   `2/12/20` <dbl>, `2/13/20` <dbl>, `2/14/20` <dbl>, `2/15/20` <dbl>,
## #   `2/16/20` <dbl>, `2/17/20` <dbl>, `2/18/20` <dbl>, `2/19/20` <dbl>, ...

4.1.3. Importar data desde un directorio

Para importar datos, se tiene dos opciones desde el área de Environment/Import Dataset.

knitr::include_graphics('./img/import.png')
FIGURA 2: Importar datos desde el directorio

FIGURA 2: Importar datos desde el directorio

Al seleccionar, por ejemplo From Text (readr) se puede importar datos con formato .csv, .tsv, .txt.

knitr::include_graphics('./img/importview.png')
FIGURA 3: Importar datos tipo .csv, .txt, .tsv desde el directorio

FIGURA 3: Importar datos tipo .csv, .txt, .tsv desde el directorio

Sin embargo, este procedimiento se recomienda utilizar solamente para archivos múltiples o grandes; en ese caso es mejor utilziar instrucciones con códigos.

4.1.4 Importar data desde un directorio con código

Se tiene documentos con diferentes extensiones, para ello se tienen paquetes y funciones que permiten importar estos archivos.

4.1.4.1 Archivos .csv, .txt

Para importar archivos con código se utiliza el paquete readr que soporta la carga de los siguientes tipos de formatos.

Tipo de dato Instrucción
Separado por coma (CSV) (coma, punto y coma, espacio blanco) read_csv()
Separado por tab (TSV) read_tsv()
Delimitación general read_delim()
Con ancho fijo read_fwf()
Tipo tabular separados por espacios en blanco read_table()
Archivos web tipo log read_log()

Una alternativa a la read_formato() es la función fread() del paquete data.table el cual es una versión mejorada de data.frame .

# Guardar data de un archivo csv
getwd()
## [1] "D:/GDrive/IKIAM/CLASES/2021II/2021II_GBI6/2021II_Clases/2021II_R/2021II_4.1_IntroduccionR_TiposDatos"
df_neutrophils <- read.csv("data/neutrophils.csv") 
head(df_neutrophils,2)
##       DMSO   TGX.221    PI103     Akt1
## 1 144.4393  99.61073 41.95241 111.8013
## 2 135.7167 115.35760 57.46430 124.1805
# Guardar data de un archivo tsv
df_chrdata <- read.csv("data/chr_data.txt") 
head(df_chrdata,2)
##   chr.position.GM06990_ABL1.GM06990_MLLT3
## 1           8\t1\t-0.046610519\t-0.181629164
## 2        8\t100001\t0.256050886\t0.462550726
df_chrdata <- read_tsv("data/chr_data.txt") 
head(df_chrdata,2)
## # A tibble: 2 x 4
##     chr position GM06990_ABL1 GM06990_MLLT3
##   <dbl>    <dbl>        <dbl>         <dbl>
## 1     8        1      -0.0466        -0.182
## 2     8   100001       0.256          0.463
# Guardar data de un archivo delim
df_brainBodyWeight <- read_delim("data/brain_bodyweight.txt", delim ="\t") 
head(df_brainBodyWeight,2)
## # A tibble: 2 x 6
##   Species   Category      body brain log.brain log.body
##   <chr>     <chr>        <dbl> <dbl>     <dbl>    <dbl>
## 1 Cow       Domesticated 465    423       8.72     8.86
## 2 Grey Wolf Wild          36.3  120.      6.90     5.18
# Guardar data de un archivo grande
library(data.table)
df_eeh1997 <- fread("data/EEH_1997.csv")
head(df_eeh1997,2)
##    d_r codestad proubies canubies parubies estsalud claestsa tipestsa entestsa
## 1:  NA      EEH        1        1       50        2       10        3        8
## 2:  NA      EEH        1        1       50        2       10        3        8
##    secestsa bolestsa aniestad mesestad ordegrpa conedadp edapacie sexpacie
## 1:        2        1     1997        1        1        3       48        2
## 2:        2        1     1997        1        2        3       84        2
##    prorespa canrespa parrespa diaingpa mesingpa aniingpa diaegrpa mesegrpa
## 1:        1        1       50       30       12     1996        1        1
## 2:        1        1       50       31       12     1996        1        1
##    diaestad conegrpa cau9nare cau307r9 cau050r9
## 1:        2        1     0091       16        1
## 2:        1        1     7840      468      600
# Comparación de tiempo fread() vs csv.read()
tiempo_fread <- system.time(fread("data/EEH_1997.csv"))
tiempo_readcsv <- system.time(read.csv("data/EEH_1997.csv"))
df_tiempo <- rbind(tiempo_fread, tiempo_readcsv)
df_tiempo
##                user.self sys.self elapsed user.child sys.child
## tiempo_fread        0.58     0.06    0.42         NA        NA
## tiempo_readcsv      8.66     0.28    9.11         NA        NA
print(paste("fread() es", round(df_tiempo[2,1]/df_tiempo[1,1],2), "veces más rápida que read.csv()"))
## [1] "fread() es 14.93 veces más rápida que read.csv()"

4.1.4.2 Archivos .sas

Los archivos .sas son un tipo de archivos estrucuturados que se leen con el software SAS. Se requiere instalar el paquete haven y utilizar la función read_sas(). Se puede encontrar ejemplos de archivos .sas en http://www.principlesofeconometrics.com/sas.htm.

# Guardar data de un archivo sas
#if(require("haven")) install.packages("haven")
library("haven")
df_sas <- read_sas('data/alcohol.sas7bdat')
head(df_sas, 3)
## # A tibble: 3 x 4
##   ADULTS  KIDS INCOME CONSUME
##    <dbl> <dbl>  <dbl>   <dbl>
## 1      2     2    758       1
## 2      2     3   1785       1
## 3      3     0   1200       1

4.1.4.3 Archivos spss .sav

R puede leer datos directamente de spss utilizando el paquete foreign con la la función read.spss() o el paquete haven y su función read_spss(). Se puede encontrar ejemplos de archivos .sav en http://spss.allenandunwin.com.s3-website-ap-southeast-2.amazonaws.com/data-files.html#.X3z_rXX0m00.

# Guardar data de un archivo csv
df_spss <- read_spss("data/sleep.sav")
head(df_spss, 1)
## # A tibble: 1 x 55
##      id        sex   age        marital edlevel weight height healthrate fitrate
##   <dbl>  <dbl+lbl> <dbl>      <dbl+lbl> <dbl+l>  <dbl>  <dbl>  <dbl+lbl> <dbl+l>
## 1    83 0 [female]    42 2 [married/de~ 2 [sec~     52    162 10 [very ~       7
## # ... with 46 more variables: weightrate <dbl+lbl>, smoke <dbl+lbl>,
## #   smokenum <dbl>, alchohol <dbl>, caffeine <dbl>, hourwnit <dbl>,
## #   hourwend <dbl>, hourneed <dbl>, trubslep <dbl+lbl>, trubstay <dbl+lbl>,
## #   wakenite <dbl+lbl>, niteshft <dbl+lbl>, liteslp <dbl+lbl>,
## #   refreshd <dbl+lbl>, satsleep <dbl+lbl>, qualslp <dbl+lbl>,
## #   stressmo <dbl+lbl>, medhelp <dbl+lbl>, problem <dbl+lbl>,
## #   impact1 <dbl+lbl>, impact2 <dbl+lbl>, impact3 <dbl+lbl>, ...

4.1.4.4 Archivos .xls .xlsx

Par leer archivos excel, se tiene el paquete readxl con la la función read_excel() o el paquete xlsx y su función read.xlsx().

# Guardar data de un archivo xlsx o xls
#if(require("readxl")) install.packages("readxl")
library("readxl")
df_xlsx <- read_excel("data/poblacion.xlsx")
head(df_xlsx, 3)
## # A tibble: 3 x 8
##     Nro `First Name` `Last Name` Gender Country         Age Date          Id
##   <dbl> <chr>        <chr>       <chr>  <chr>         <dbl> <chr>      <dbl>
## 1     1 Dulce        Abril       Female United States    32 15/10/2017  1562
## 2     2 Mara         Hashimoto   Female Great Britain    25 16/08/2016  1582
## 3     3 Philip       Gent        Male   France           36 21/05/2015  2587

4.2. Manipulación de datos

4.2.1 Datos ordenados (tidy data)

En los datos con las cuales se trabaja usualmente, se tiene elementos que pueden estar desordenados. El dato ordenado, tidy data, ayuda a optimizar el tiempo en el análisis de datos y tiene las siguientes características:

  • Cada columna es una variable

  • Cada fila es una observación

  • Cada celda tiene un único valor

knitr::include_graphics('./img/tidystr.png')
FIGURA 4: Características del dato ordenado (tidy data)

FIGURA 4: Características del dato ordenado (tidy data)

La librería tidyr es la que se utiliza para ordenar los datos. Las funciones de esta librería se agrupan en algunas categorías:

  1. Pivotting, sirven para convertir a datos extensos en compactos o viceversa, para ello se tienen las funciones pivot_longer(), pivot_wider() que son equivalentes a las funciones anbteriores gather() y spread() respectivamente.

  2. Rectangling, ordenan tablas altamente anidados en datos ordenados, para ello se tienen las funciones unnest_longer(), unnest_wider() y hoist().

  3. Nesting, se convierte datos agrupados donde cada grupo se convierte en una columan, para ello se utilizan las funciones nest() y unnest.

  4. Splitting y comdinación de columnas de character, se utiliza separate() y extract() que separa una columna simple de character a columnas múltiples; por otro lado se utiliza unite() para reagrupar columnas de character.

  5. Valores ausentes, convertir en valores explícitos con complete(), anularlos con drop_na(), reemplazar con valores previos o posteriores con fill() o cambiar por un valor con replace_na.

En esta etapa lo que se busca es ordenar los datos y además de limpiar o corregir las mismas.

4.4. Operador “pipe” %>%

El operador pipe %>% equivale a un agregador (+) de procesos. Por ejemplo si se tiene un dataframe se realiza una agrupación, luego se realiza un suma, luego se evalua un promedio, entonces esta secuencia de procesos se podría resumir como:

dataframe %>% agrupacion %>% suma() %>% promedio

Este operador es altamente utilizado para procesar datos con las librerías de tidyverse. El operador pipe evita tener confusiones como cuando se tiene muchos procesos con ( ), como por ejemplo la operación:

# Se tiene e siguiente vector
valores <- c(0.109, 0.359, 0.63, 0.996, 0.515, 0.142, 0.017, 0.829, 0.907)

# Se realiza las operaciones en el siguiente orden: logaritmo, coseno, exponencial, redondeo y orden
sort(round(exp(cos(log(valores))), 1))
## [1] 0.5 0.6 0.7 1.7 2.2 2.4 2.7 2.7 2.7
# Utilizanzando el operador pipe se tendría lo siguiente: 
#       valores %>% logaritmo %>% coseno %>% exponencial %>% redondeo %>% orden
valores_piped <- valores %>% log() %>% cos() %>% exp() %>% round(1) %>% sort()
valores_piped
## [1] 0.5 0.6 0.7 1.7 2.2 2.4 2.7 2.7 2.7

Como se evidencia, al utilizar el operador %>% se facilita diferenciar como es la secuencia de procesamiento de la data.

knitr::include_graphics('./img/tidyv-flow.png')
FIGURA 5: Operador pipe %>% en tidyverse y sus librerías

FIGURA 5: Operador pipe %>% en tidyverse y sus librerías

path <- "https://raw.githubusercontent.com/martintinch0/CienciaDeDatosParaCuriosos/master/data/gapminder.csv"
df_gapminder <- read.table(file = path, sep=';', header = TRUE, stringsAsFactors = FALSE)

# pivot_longer
library("tidyr")
df_gapminder2 <- df_gapminder %>% pivot_longer(!c(country, continent), names_to = "datos", values_to = "valor")

# pivot_wider
df_gapminder3 <- df_gapminder2 %>% pivot_wider(names_from = "datos", values_from = "valor", values_fn = list)

# Separate
df_gapminder4 <- df_gapminder3 %>% separate(year, paste0("A_", 1:13))

# Extract
df6 <- data.frame(x = c(NA, "a-b", "a-d", "b-c", "d-e"))
df7 <- df6 %>% extract(x, c("A", "B"), "([a-d]+)-([a-d]+)")

# Valores ausentes
df_neutrophils2 <- df_neutrophils %>% drop_na(DMSO, any_of("Akt1"))
colnames(df_neutrophils2)
## [1] "DMSO"    "TGX.221" "PI103"   "Akt1"
df_neutrophils3 <- df_neutrophils2 %>% replace_na(list(TGX.221=0))
df_neutrophils4 <- df_neutrophils3 %>% fill(PI103, .direction = "down")

4.5. Procesamiento de datos (data wrangling)

Después de tener la data ordenada (tidy data) se requiere hacer procesamientos de cálculo, selección, filtrado, resumen o rearreglo. Estas operaciones se pueden implementar utilizando la librería dplyr. Esta librería tiene las siguientes opciones:

Funciones de la librería dplyr
Función Descripción
mutate() Adiciona nuevas variables basados en las operaciones con otras columnas
select() Selecciona variables basados en sus nombres
filter() Selecciona casos basados en valores condicionados
summarise() Reduce los múltiples valores en una tabla resumen
arrange() Cambia el orden de las filas
group_by() Permite operar por grupos

4.5.1. Función select()

El comando select() permite seleccionar columnas de data frames utilizando solamente los nombres de las variables deseadas.

library(ggplot2) # librería de visualizacion que tiene datasets adicionales como "diamond"
library(dplyr)
# Data inicial
df_diamonds <- diamonds
colnames(df_diamonds)
##  [1] "carat"   "cut"     "color"   "clarity" "depth"   "table"   "price"  
##  [8] "x"       "y"       "z"
# Data de columnas seleccionadas
df_diamonds_clar <- df_diamonds %>% select(cut, clarity, price)
colnames(df_diamonds_clar)
## [1] "cut"     "clarity" "price"
# Formas de generar vectores con una columna de dataframe
diamonds_precio <- df_diamonds$price
str(diamonds_precio)
##  int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
diamonds_cut <- df_diamonds %>% pull(cut)  # crear vector con pull()
diamonds_color <- df_diamonds %>% select(color) %>% unlist()  # crear vector con unlist()

# Elementos únicos en una columna
length(unique(diamonds_color))
## [1] 7

4.5.2. Función filter()

La función filter() permite seleccionar datos de acuerdo a los que toman en una o más variable.

# Filtro de diamond_df con corte "cut" == "fair"
df_diamonds_fair <- df_diamonds %>% filter (cut == "Fair")
summary(df_diamonds_fair)
##      carat              cut       color      clarity        depth      
##  Min.   :0.220   Fair     :1610   D:163   SI2    :466   Min.   :43.00  
##  1st Qu.:0.700   Good     :   0   E:224   SI1    :408   1st Qu.:64.40  
##  Median :1.000   Very Good:   0   F:312   VS2    :261   Median :65.00  
##  Mean   :1.046   Premium  :   0   G:314   I1     :210   Mean   :64.04  
##  3rd Qu.:1.200   Ideal    :   0   H:303   VS1    :170   3rd Qu.:65.90  
##  Max.   :5.010                    I:175   VVS2   : 69   Max.   :79.00  
##                                   J:119   (Other): 26                  
##      table           price             x                y         
##  Min.   :49.00   Min.   :  337   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.:56.00   1st Qu.: 2050   1st Qu.: 5.630   1st Qu.: 5.570  
##  Median :58.00   Median : 3282   Median : 6.175   Median : 6.100  
##  Mean   :59.05   Mean   : 4359   Mean   : 6.247   Mean   : 6.183  
##  3rd Qu.:61.00   3rd Qu.: 5206   3rd Qu.: 6.700   3rd Qu.: 6.640  
##  Max.   :95.00   Max.   :18574   Max.   :10.740   Max.   :10.540  
##                                                                   
##        z        
##  Min.   :0.000  
##  1st Qu.:3.610  
##  Median :3.970  
##  Mean   :3.983  
##  3rd Qu.:4.280  
##  Max.   :6.980  
## 
# Filtro de diamond_df con corte "cut" == "fair" y "price" <= 4000
df_diamonds_fair_cheap <- df_diamonds %>% filter (cut == "Fair" & price <= 4000)
summary(df_diamonds_fair_cheap)
##      carat              cut      color      clarity        depth      
##  Min.   :0.220   Fair     :979   D: 97   SI2    :273   Min.   :43.00  
##  1st Qu.:0.595   Good     :  0   E:146   SI1    :241   1st Qu.:63.95  
##  Median :0.730   Very Good:  0   F:201   VS2    :157   Median :65.00  
##  Mean   :0.766   Premium  :  0   G:197   I1     :131   Mean   :63.98  
##  3rd Qu.:0.960   Ideal    :  0   H:162   VS1    :108   3rd Qu.:65.90  
##  Max.   :1.520                   I:108   VVS2   : 49   Max.   :79.00  
##                                  J: 68   (Other): 20                  
##      table          price            x               y               z       
##  Min.   :49.0   Min.   : 337   Min.   :3.870   Min.   :3.780   Min.   :2.32  
##  1st Qu.:56.0   1st Qu.:1386   1st Qu.:5.390   1st Qu.:5.335   1st Qu.:3.33  
##  Median :58.0   Median :2318   Median :5.790   Median :5.740   Median :3.66  
##  Mean   :59.2   Mean   :2274   Mean   :5.718   Mean   :5.656   Mean   :3.64  
##  3rd Qu.:61.0   3rd Qu.:3050   3rd Qu.:6.140   3rd Qu.:6.070   3rd Qu.:3.98  
##  Max.   :79.0   Max.   :3992   Max.   :7.260   Max.   :7.130   Max.   :4.80  
## 
# Filtro de diamond_df con corte "cut" == "fair" y "price" <= 4000  o color !=c("G", "E")
df_diamonds_multfiltro <- df_diamonds %>% filter (cut == "Fair" & price <= 4000 | color !=c("G", "E"))
summary(df_diamonds_multfiltro)
##      carat               cut        color       clarity          depth      
##  Min.   :0.2000   Fair     : 1514   D:6775   SI1    :10930   Min.   :43.00  
##  1st Qu.:0.4000   Good     : 4030   E:4981   VS2    : 9869   1st Qu.:61.10  
##  Median :0.7100   Very Good: 9721   F:9542   SI2    : 7652   Median :61.90  
##  Mean   :0.8168   Premium  :11173   G:5789   VS1    : 6489   Mean   :61.76  
##  3rd Qu.:1.0600   Ideal    :17183   H:8304   VVS2   : 3830   3rd Qu.:62.50  
##  Max.   :5.0100                     I:5422   VVS1   : 2834   Max.   :79.00  
##                                     J:2808   (Other): 2017                  
##      table           price             x                y         
##  Min.   :43.00   Min.   :  326   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.:56.00   1st Qu.:  968   1st Qu.: 4.730   1st Qu.: 4.740  
##  Median :57.00   Median : 2513   Median : 5.730   Median : 5.740  
##  Mean   :57.49   Mean   : 4008   Mean   : 5.773   Mean   : 5.776  
##  3rd Qu.:59.00   3rd Qu.: 5395   3rd Qu.: 6.580   3rd Qu.: 6.570  
##  Max.   :95.00   Max.   :18823   Max.   :10.740   Max.   :58.900  
##                                                                   
##        z         
##  Min.   : 0.000  
##  1st Qu.: 2.930  
##  Median : 3.540  
##  Mean   : 3.565  
##  3rd Qu.: 4.050  
##  Max.   :31.800  
## 
# Filtro de df_spss con is.na(age)
colnames(df_spss)
##  [1] "id"           "sex"          "age"          "marital"      "edlevel"     
##  [6] "weight"       "height"       "healthrate"   "fitrate"      "weightrate"  
## [11] "smoke"        "smokenum"     "alchohol"     "caffeine"     "hourwnit"    
## [16] "hourwend"     "hourneed"     "trubslep"     "trubstay"     "wakenite"    
## [21] "niteshft"     "liteslp"      "refreshd"     "satsleep"     "qualslp"     
## [26] "stressmo"     "medhelp"      "problem"      "impact1"      "impact2"     
## [31] "impact3"      "impact4"      "impact5"      "impact6"      "impact7"     
## [36] "stopb"        "restlss"      "drvsleep"     "drvresul"     "ess"         
## [41] "anxiety"      "depress"      "fatigue"      "lethargy"     "tired"       
## [46] "sleepy"       "energy"       "stayslprec"   "getsleprec"   "qualsleeprec"
## [51] "totsas"       "cigsgp3"      "agegp3"       "probsleeprec" "drvslprec"
df_spss_isna <- df_spss %>% filter (is.na(age))
dim(df_spss_isna)
## [1] 23 55
# Filtro de df_spss con age entre 12 y 30
df_spss_joven <- df_spss %>% filter (between(age, 12, 30))
dim(df_spss_joven)
## [1] 44 55
# Filtro de df_spss con edlevel de 3 y 4
df_spss_educ <- df_spss %>% filter (edlevel %in% c(3,4))
dim(df_spss_educ)
## [1] 101  55

4.5.3. Función arrange()

La función arrange() permite ordenar los datos en orden ascendente o descendente en base a los valores de las variables. Es informativo porque se puede revisar los valores extermos.

# df_gapminder ordenado por "gdpPercap"
df_gapminder_asc <- df_gapminder %>% arrange (gdpPercap)
head(df_gapminder_asc,5)
##            country continent year lifeExp      pop gdpPercap
## 1 Congo, Dem. Rep.    Africa 2002  44.966 55379852  241.1659
## 2 Congo, Dem. Rep.    Africa 2007  46.462 64606759  277.5519
## 3          Lesotho    Africa 1952  42.138   748747  298.8462
## 4    Guinea-Bissau    Africa 1952  32.500   580653  299.8503
## 5 Congo, Dem. Rep.    Africa 1997  42.587 47798986  312.1884
# df_gapminder ordenado por "gdpPercap" en forma descendente
df_gapminder_desc <- df_gapminder %>% arrange(desc(gdpPercap))
head(df_gapminder_desc,5)
##   country continent year lifeExp    pop gdpPercap
## 1  Kuwait      Asia 1957  58.033 212846 113523.13
## 2  Kuwait      Asia 1972  67.712 841934 109347.87
## 3  Kuwait      Asia 1952  55.565 160000 108382.35
## 4  Kuwait      Asia 1962  60.470 358266  95458.11
## 5  Kuwait      Asia 1967  64.624 575003  80894.88
# df_gapminder filtrado por "Americas" y ordenado por "gdpPercap" en forma descendente
df_gapminder_AmerDesc <- df_gapminder %>% filter(continent == "Americas") %>% arrange(desc(gdpPercap))
head(df_gapminder_AmerDesc,5)
##         country continent year lifeExp       pop gdpPercap
## 1 United States  Americas 2007  78.242 301139947  42951.65
## 2 United States  Americas 2002  77.310 287675526  39097.10
## 3        Canada  Americas 2007  80.653  33390141  36319.24
## 4 United States  Americas 1997  76.810 272911760  35767.43
## 5        Canada  Americas 2002  79.770  31902268  33328.97

4.5.4. Función mutate()

La función mutate() permite crear nuevas variables como resultado de operar otras variables del dataframe. La función tiene la siguiente forma: ...%>% mutate(nombre_columna_nueva = valor_calculado)

# df_iris calcular area del sépalo
df_iris <- iris
df_iris_areasep <- df_iris %>% mutate (area_sepal = Sepal.Length*Sepal.Width)
head(df_iris_areasep,5)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species area_sepal
## 1          5.1         3.5          1.4         0.2  setosa      17.85
## 2          4.9         3.0          1.4         0.2  setosa      14.70
## 3          4.7         3.2          1.3         0.2  setosa      15.04
## 4          4.6         3.1          1.5         0.2  setosa      14.26
## 5          5.0         3.6          1.4         0.2  setosa      18.00

4.5.5. Función group_by() y summary()

La función group_by() permite agrupar las filas en base a las categorías de alguna variable; luego de agrupar se puede aplicar una transformación - cálculo con la función summary(). Esta combinación tiene la siguiente forma: data %>% group_by(variable) %>% summarise(nombre_tranformacion= valor_calculado)

# df_msleep agrupado por orden y calculado el promedio de horas de sueño
df_msleep <- msleep
df_msleep_group <- df_msleep %>% group_by (order) %>% summarise(sleept_mean = signif(mean(sleep_total, na.rm = TRUE),2))
df_msleep_group %>% arrange(sleept_mean)
## # A tibble: 19 x 2
##    order           sleept_mean
##    <chr>                 <dbl>
##  1 Perissodactyla          3.5
##  2 Proboscidea             3.6
##  3 Artiodactyla            4.5
##  4 Cetacea                 4.5
##  5 Hyracoidea              5.7
##  6 Lagomorpha              8.4
##  7 Monotremata             8.6
##  8 Scandentia              8.9
##  9 Carnivora              10  
## 10 Erinaceomorpha         10  
## 11 Primates               10  
## 12 Soricomorpha           11  
## 13 Diprotodontia          12  
## 14 Rodentia               12  
## 15 Pilosa                 14  
## 16 Afrosoricida           16  
## 17 Cingulata              18  
## 18 Didelphimorphia        19  
## 19 Chiroptera             20
# df_msleep agrupado por dieta, se calcula número de individuos, index_brainwt/bodywt, awake_mean y sleep_mean 
colnames(df_msleep)
##  [1] "name"         "genus"        "vore"         "order"        "conservation"
##  [6] "sleep_total"  "sleep_rem"    "sleep_cycle"  "awake"        "brainwt"     
## [11] "bodywt"
df_msleep_brain <- df_msleep %>% group_by(vore) %>% 
  summarise(muestra = length(vore),
            index_brain_body = mean(brainwt/bodywt, na.rm = TRUE),
            awake_mean = mean(awake),
            sleep_mean = mean(sleep_total))
df_msleep_brain
## # A tibble: 5 x 5
##   vore    muestra index_brain_body awake_mean sleep_mean
##   <chr>     <int>            <dbl>      <dbl>      <dbl>
## 1 carni        19          0.00711      13.6       10.4 
## 2 herbi        32          0.00718      14.5        9.51
## 3 insecti       5          0.0122        9.06      14.9 
## 4 omni         20          0.0155       13.1       10.9 
## 5 <NA>          7          0.00974      13.8       10.2

4.5.6. Unir datos join()

Al tener dos o más datos donde una o varias columnas coinciden, con la función join() se integra nueva información en base a una (o más) columnas en las que coinciden. Se tiene cuatro tipos de join():

  • inner_join() retorna las columnas que coinciden entre ambos.

  • left_join() retorna las columnas de x y las columnas que coinciden entre x e y.

  • right_join() retorna las columnas de y y las columnas que coinciden entre x e y.

  • full_join()retorna las columnas de x e y.

La forma genérica de la función join es la siguiente:

tipo_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)

Las celdas que no tienen coincidencia son rellenadas con NA.

# Datos 
areas_inv <- data.frame(InvId = sample(1:20, 20, replace=FALSE), 
                  Product = sample(c("Genomica","Agua","Rocas", 
                                     "Anfibios"), 20, replace = TRUE),
                  Tesistas = sample (1:4, 10, replace = TRUE))

institucion <- data.frame(InvId = sample(1:20, 15, replace=FALSE), 
                  Instituto = sample(c("Ikiam","YachayTech","EPN", "ESPOCH",
                                       "USFQ"), 15, replace = TRUE), 
                  Fondos = sample(c("Institucional","Nacional","Internacional"), 
                             15, replace = TRUE))


# inner_join()
invest_inner <- areas_inv %>% inner_join(institucion, by = "InvId")
dim(invest_inner)
## [1] 15  5
# left_join()
invest_leftj <- areas_inv %>% left_join(institucion, by = "InvId")
dim(invest_leftj)
## [1] 20  5
# right_join()
invest_rightj <- areas_inv %>% right_join(institucion, by = "InvId")
dim(invest_rightj)
## [1] 15  5
# full_join()
invest_fullj <- areas_inv %>% full_join(institucion, by = "InvId")
dim(invest_fullj)
## [1] 20  5

4.6. Manipulación de datos con data.table

data.table es un paquete de R que premite manipular datos con las operaciones de subset, group, update, join y otras operaciones. Esta librería permite que se opere con mayor eficiencia en el memoria y tiempo de computación. Es recomendable cuando se tiene datos grandes las cuales se cargan con la instrucción fread(). Si se desea crear una tabla la instrucción tiene una estructura similar al nombre <- data.frame (parámetros), en su lugar es nombre <- data.table (parámetros).

# Datos predeterminados 
library(data.table)
df_fligths <- fread("https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv")
colnames(df_fligths)
##  [1] "year"      "month"     "day"       "dep_delay" "arr_delay" "carrier"  
##  [7] "origin"    "dest"      "air_time"  "distance"  "hour"
# Subset 
unique(df_fligths$dest)
##  [1] "LAX" "PBI" "MIA" "SEA" "SFO" "BOS" "ORD" "IAH" "AUS" "DFW" "STT" "SJU"
## [13] "LAS" "MCO" "EGE" "CHS" "FLL" "RSW" "BTV" "BUF" "IAD" "PWM" "SYR" "RDU"
## [25] "JAX" "HOU" "DEN" "ROC" "SAN" "BQN" "LGB" "PSE" "TPA" "PHX" "SMF" "SRQ"
## [37] "SJC" "SLC" "ABQ" "OAK" "BUR" "PDX" "MSY" "CLT" "ATL" "DTW" "MSP" "DAY"
## [49] "MHT" "DCA" "SDF" "CLE" "STL" "MEM" "BNA" "GSP" "MSN" "OMA" "IND" "RIC"
## [61] "PVD" "AVL" "MCI" "OKC" "MKE" "TUL" "PIT" "SAV" "BWI" "GSO" "GRR" "DSM"
## [73] "CVG" "ORF" "BHM"
##  [ reached getOption("max.print") -- omitted 34 entries ]
df_fligths_chic <- df_fligths[origin == "JFK" & dest == "JAX" & month == 6L]
dim(df_fligths_chic)
## [1] 87 11
# Ordenar
unique(df_fligths$origin)
## [1] "JFK" "LGA" "EWR"
df_fligths_ord <- df_fligths[order(origin, -air_time)] # descendente para air_time
head(df_fligths_ord, 5)
##    year month day dep_delay arr_delay carrier origin dest air_time distance
## 1: 2014     3   2        24        87      UA    EWR  HNL      706     4963
## 2: 2014     3   4        -1        61      UA    EWR  HNL      697     4963
## 3: 2014     1  26        13        58      UA    EWR  HNL      688     4963
## 4: 2014     2  26         5        90      UA    EWR  HNL      676     4963
## 5: 2014     2  15         6        44      UA    EWR  HNL      674     4963
##    hour
## 1:    9
## 2:    9
## 3:    9
## 4:    9
## 5:    9
# Selecccionar filas
df_fligths_fila <- df_fligths[5:7]
df_fligths_fila
##    year month day dep_delay arr_delay carrier origin dest air_time distance
## 1: 2014     1   1         2         1      AA    JFK  LAX      350     2475
## 2: 2014     1   1         4         0      AA    EWR  LAX      339     2454
## 3: 2014     1   1        -2       -18      AA    JFK  LAX      338     2475
##    hour
## 1:   13
## 2:   18
## 3:   21
# Selecccionar columnas
df_fligths_columna <- df_fligths[5:7, 7:11]
df_fligths_columna
##    origin dest air_time distance hour
## 1:    JFK  LAX      350     2475   13
## 2:    EWR  LAX      339     2454   18
## 3:    JFK  LAX      338     2475   21
df_fligths_columna <- df_fligths[1:7, .(dep_delay,arr_delay,carrier)]
df_fligths_columna
##    dep_delay arr_delay carrier
## 1:        14        13      AA
## 2:        -3        13      AA
## 3:         2         9      AA
## 4:        -8       -26      AA
## 5:         2         1      AA
## 6:         4         0      AA
## 7:        -2       -18      AA
selectores <- c("origin", "dest", "air_time")
df_fligths_selector <- df_fligths[1:7, ..selectores]
df_fligths_selector
##    origin dest air_time
## 1:    JFK  LAX      359
## 2:    JFK  LAX      363
## 3:    JFK  LAX      351
## 4:    LGA  PBI      157
## 5:    JFK  LAX      350
## 6:    EWR  LAX      339
## 7:    JFK  LAX      338
# Número de vuelos queno tuvieron delay (>0) 
df_fligths_calc <- df_fligths[, sum((dep_delay+arr_delay)>0)]
df_fligths_calc
## [1] 108239
# Agrupar
flight_group <- df_fligths[, .N, by = .(origin, carrier)]
flight_group
##     origin carrier     N
##  1:    JFK      AA 11923
##  2:    LGA      AA 11730
##  3:    EWR      AA  2649
##  4:    EWR      AS   574
##  5:    JFK      B6 34220
##  6:    EWR      B6  5473
##  7:    LGA      B6  4786
##  8:    LGA      DL 18670
##  9:    EWR      DL  4153
## 10:    JFK      DL 18860
## 11:    EWR      EV 28328
## 12:    LGA      EV 10422
## 13:    LGA      F9   473
## 14:    LGA      FL  1251
## 15:    JFK      HA   260
## 16:    LGA      MQ 12948
## 17:    JFK      MQ  5444
## 18:    JFK      VX  3138
## 19:    EWR      VX  1644
## 20:    EWR      WN  4807
## 21:    LGA      WN  7095
## 22:    EWR      MQ   167
## 23:    JFK      EV  1069
## 24:    EWR      UA 36124
## 25:    LGA      UA  6219
##  [ reached getOption("max.print") -- omitted 8 rows ]
flight_mean <- df_fligths[dest == "MIA", .(mean_arrdelay = mean(arr_delay),
                           mean_depdelay = mean(dep_delay)), 
                       by = .(origin, dest, month)]

dim(flight_mean)
## [1] 30  5

En conclusión data.table es una forma rápida de manipular y transformar data grande. Puede revisar todas las funcionalidades de ese paquete en su página de referencia: https://rdatatable.gitlab.io/data.table/.

TAREA: MANIPULACIÓN DE DATOS

Realice las siguientes actividades en un documento .Rmd

Carga información

Utilizando las librerías RCurl, readr, readxl y data.table cargue los siguientes archivos asignando indetificadores adecuados:

  • Busque un archivo tipo .txt o .csv en GitHub (https://github.com) que se relacione a alguna area y que esté asociado al uso de R para su análisis.

  • Cargue el archivo “expr_data.txt” de la carpeta data

  • Cargue el archivo “SEST17_micro_35755_20191209_CSV.csv” de la carpeta data utilizando fread() y read.csv y compare los tiempos que requieren para cargar el archivo.

  • Cargue el archivo “barriosOriginal” desde el url.

  • Asigne a un data frame la data precargada de R mpg, puede requerir la librería ggplot2.

# Coloque aquí las librerías

# Escriba aquí las instrucciones para cargar los archivos. 

Ordenar datos (tidy data)

Utilice la librería tidyr para arreglar la información cargada en el paso 5.1.

  • Revise que cada datos esté estructurada de manera que cada columna sea una variable, que cada fila sea una observación y que cada celda sea un valor.
# Coloque aquí las librerías

# Escriba aquí las instrucciones para obtener un tidy data.
# Puede requerir anular datos tipo "NaN" o "NA"

Procesamiento de datos

  1. Utilice la librería dplyr o data.table con la data de mpg y barriosOriginal:
  • Seleccionar select()

  • Filtrar filter()

  • Ordenar arrange()

  • Calcular mutate()

  • Agrupar y resumir group_by y summarise()

  1. Genere dos dataframes con diferentes contenidos, pero al menos una columna corresponde a la misma variable y aplique las diferentes formas agregar data de diferentes archivos utilizando la función ..._join().
# Coloque aquí las librerías

# Escriba aquí las instrucciones para procesar la data.

# Escriba aquí las instrucciones para usar la función ..._join()